jQuery Mouse Events and Touch Events (and the Modern Pointer Events Way)

Blog / JavaScript · February 6, 2015 · Updated June 10, 2026 · 10 min read
jQuery Mouse Events and Touch Events (and the Modern Pointer Events Way)

jQuery mouse events (like .click(), .dblclick(), .hover(), .mousedown()) and touch events (tap, swipe, touchstart) let you respond to user input, but in 2026 the recommended approach for new code is the native Pointer Events API (pointerdown, pointermove, pointerup, pointercancel) in plain JavaScript, which handles mouse, touch, and pen with one set of handlers — removing the old mouse-vs-touch duplication entirely.

This guide covers both worlds. If you maintain a jQuery codebase, the first half is a clean reference for every mouse and touch event. If you are writing new code or modernizing, the second half shows the vanilla-JS equivalents and why you usually no longer need jQuery — or separate touch handlers — at all.

Key takeaways

  • Events are user actions a page can react to (click, double-click, hover, drag, touch). The function you attach is the event handler.
  • In modern jQuery, every shortcut like .click(fn) is just sugar for .on('click', fn); remove handlers with .off('click'). The old .bind()/.unbind() and .toggle(fn, fn) APIs are deprecated — use .on()/.off().
  • For touch, jQuery core has no tap/swipe; those came from the now-retired jQuery Mobile plugin. Prefer native events instead.
  • The Pointer Events API unifies mouse, touch, and pen. One pointerdown/pointermove/pointerup handler replaces parallel mouse and touch code.
  • Add the CSS touch-action property to control gestures, and use passive listeners ({ passive: true }) for smooth scrolling.
  • jQuery is optional on modern projects: addEventListener, closest(), and Pointer Events cover almost everything jQuery events did.

What is an event and an event handler?

An event is any action the browser can detect and respond to — a mouse click, a key press, a page finishing loading, a form submission, or a finger touching the screen. An event handler is the function you run when that event fires.

Common examples:

  • A mouse click on a button
  • Moving the pointer over an element
  • Submitting a form
  • A key press on the keyboard
  • A finger tapping or swiping on a touchscreen

The rest of this article shows how to attach handlers the jQuery way, then the modern native way.

How do you bind events in jQuery today?

First, make sure the DOM is ready, then attach a handler. The modern, recommended jQuery method is .on() (the old .bind()/.unbind() still work but are deprecated).

// Run code once the DOM is ready
$(function () {
  // Attach a click handler with .on() (preferred)
  $('a').on('click', function (event) {
    event.preventDefault(); // stop the link from navigating
    alert('This is a click event!');
  });

  // Remove it later
  $('a').off('click');
});

A few things to know:

  • $ is just an alias for jQuery. $(fn) is shorthand for $(document).ready(fn).
  • Inside the handler, this is the element that triggered the event; the event argument carries details such as event.pageX, event.target, and event.type.
  • Call event.preventDefault() to stop the default browser behavior (such as following a link), and event.stopPropagation() to stop the event from bubbling up.
  • Every shorthand such as .click(fn) is identical to .on('click', fn), and .dblclick(fn) is .on('dblclick', fn). The shorthand methods are still available but .on()/.off() is the canonical API and the only way to use event delegation for dynamically added elements.

jQuery mouse events reference

These are the mouse events jQuery exposes. Each shorthand maps directly to an .on(eventType, handler) call.

jQuery method Underlying event Fires when
.click() click Button pressed and released over the element
.dblclick() dblclick Element is double-clicked
.contextmenu() contextmenu Right-click, before the context menu shows
.mousedown() mousedown Button is pressed over the element
.mouseup() mouseup Button is released over the element
.mousemove() mousemove Pointer moves inside the element
.mouseenter() mouseenter Pointer enters the element (does not bubble)
.mouseleave() mouseleave Pointer leaves the element (does not bubble)
.mouseover() mouseover Pointer enters the element or a child (bubbles)
.mouseout() mouseout Pointer leaves the element or a child (bubbles)
.hover() mouseenter + mouseleave Convenience for enter/leave pairs

click and dblclick

The click event fires only after the button is pressed and released while the pointer is inside the element. dblclick requires two clicks within a system-defined time window.

$('#target').on('click', function () {
  console.log('Handler for click called.');
});

$('#target').on('dblclick', function () {
  console.log('Handler for dblclick called.');
});

Avoid binding both click and dblclick to the same element: the order of events varies between browsers, and double-click sensitivity is OS- and user-configurable, so the results are unpredictable.

contextmenu

The contextmenu event is sent when the right mouse button is clicked, just before the menu appears. Returning false (or calling event.preventDefault()) suppresses the native menu.

$('#target').on('contextmenu', function (event) {
  event.preventDefault();
  console.log('Custom right-click menu here.');
});

hover, mouseenter and mouseleave

.hover(handlerIn, handlerOut) is shorthand for binding mouseenter and mouseleave. Crucially, mouseenter/mouseleave do not bubble, so they fire only for the bound element — unlike mouseover/mouseout, which also fire as the pointer crosses child elements. Prefer enter/leave to avoid spurious triggers.

// Add a class while hovering, remove it on leave
$('td').on('mouseenter', function () {
  $(this).addClass('hover');
}).on('mouseleave', function () {
  $(this).removeClass('hover');
});

// Equivalent using the .hover() shorthand
$('td').hover(
  function () { $(this).addClass('hover'); },
  function () { $(this).removeClass('hover'); }
);

// Detach both
$('td').off('mouseenter mouseleave');

mousedown, mouseup and mousemove

mousedown fires on press, mouseup on release, and mousemove continuously as the pointer moves. mousemove can fire dozens of times per second, so keep its handler lightweight or throttle it.

$('#target').on('mousedown', function () {
  console.log('mousedown');
});

$('#target').on('mouseup', function () {
  console.log('mouseup');
});

$('#target').on('mousemove', function (event) {
  console.log('Pointer at ' + event.pageX + ', ' + event.pageY);
});

Note: if a user presses outside an element, drags onto it, and releases, that still counts as a mouseup. For genuine button presses, prefer click.

Also note two retired APIs you may see in old code: .bind()/.unbind() (replaced by .on()/.off()) and the event form .toggle(handler1, handler2) that alternated handlers on each click — it was deprecated in jQuery 1.8 and removed in 1.9. Today, track state yourself or use .on('click', ...) with a flag. ($.fn.toggle() for showing/hiding elements is a different, still-supported animation method.)

What about jQuery touch events?

This is the part most in need of modernizing. jQuery core has no tap, taphold, or swipe events — those came from the jQuery Mobile plugin, which was officially deprecated and is no longer maintained. New projects should not adopt it.

For reference, the old jQuery Mobile touch events were:

jQuery Mobile event Fires when the user…
tap Quickly taps an element
taphold Taps and holds (~750ms)
swipe Drags horizontally more than ~30px
swipeleft Swipes right-to-left
swiperight Swipes left-to-right

If you are maintaining a legacy jQuery Mobile page, see our dedicated walkthrough on how to use jQuery Mobile touch events. For everything new, use the native events below instead.

The modern way: Pointer Events in vanilla JavaScript

The browser-native Pointer Events API is the recommended approach in 2026. A pointer is any input device — mouse, touch, or stylus — so a single set of handlers covers all of them. This eliminates the classic problem this article was originally about: writing parallel mouse and touch code.

Mouse Events Touch Events Pointer Events
Mouse Yes No Yes
Touch No Yes Yes
Pen / stylus No No Yes
Multi-touch No Yes Yes (via pointerId)
Recommendation Legacy only Special cases Use this for new code

The core events are pointerdown, pointermove, pointerup, and pointercancel (fired when the system takes over the gesture, e.g. a scroll). Attach them with addEventListener.

const box = document.querySelector('#target');

box.addEventListener('pointerdown', (event) => {
  // event.pointerType is 'mouse', 'touch', or 'pen'
  console.log('pointerdown via', event.pointerType, 'at', event.clientX, event.clientY);
});

box.addEventListener('pointermove', (event) => {
  console.log('moving', event.clientX, event.clientY);
});

box.addEventListener('pointerup', (event) => {
  console.log('pointerup');
});

box.addEventListener('pointercancel', () => {
  console.log('gesture cancelled by the browser');
});

jQuery to vanilla JavaScript cheat sheet

Most jQuery event code maps cleanly onto addEventListener. Use closest() for delegation and matches() to filter targets.

jQuery Vanilla JavaScript
$('#el').on('click', fn) el.addEventListener('click', fn)
$('#el').off('click', fn) el.removeEventListener('click', fn)
$('#el').click() el.click() / el.dispatchEvent(new Event('click'))
$(document).ready(fn) document.addEventListener('DOMContentLoaded', fn)
$('.box').on('mouseenter', fn) box.addEventListener('mouseenter', fn)
$(document).on('click', '.row', fn) (delegation) document.addEventListener('click', e => { if (e.target.closest('.row')) fn(e); })
jQuery Mobile tap / swipe pointerdown + pointerup (compare time/distance)

Tap and swipe with Pointer Events

You don't need a library for taps and swipes. Compare the start and end pointer positions and the elapsed time.

const el = document.querySelector('#target');
let startX = 0;
let startTime = 0;

el.addEventListener('pointerdown', (event) => {
  startX = event.clientX;
  startTime = Date.now();
});

el.addEventListener('pointerup', (event) => {
  const dx = event.clientX - startX;
  const dt = Date.now() - startTime;

  if (Math.abs(dx) < 10 && dt < 250) {
    console.log('tap');
  } else if (dx <= -30) {
    console.log('swipe left');
  } else if (dx >= 30) {
    console.log('swipe right');
  }
});

touch-action and passive listeners

Two small but important details make pointer-based UIs feel right:

  • touch-action (CSS) tells the browser which native gestures to keep. For a custom horizontal swipe that should not interfere with vertical scrolling, use touch-action: pan-y;. To handle all gestures yourself, use touch-action: none;.
  • Passive listeners improve scroll performance. When a listener never calls preventDefault(), register it as passive so the browser can scroll without waiting for your code.
/* CSS: allow vertical scroll, handle horizontal ourselves */
#target {
  touch-action: pan-y;
}
// JS: passive listener for smooth scrolling
window.addEventListener('pointermove', onMove, { passive: true });

function onMove(event) {
  // Read-only work here; do NOT call event.preventDefault()
}

Should you still use jQuery for events?

For brand-new projects, usually no. Native addEventListener, closest() for delegation, and Pointer Events cover virtually everything jQuery's event system did, with no dependency to load. jQuery remains a perfectly reasonable choice when you are maintaining an existing jQuery codebase — there is no need for a risky rewrite just to remove it.

A pragmatic path: keep jQuery where it lives, but write new interactions with native Pointer Events, and migrate hot spots incrementally. If you want help modernizing a legacy front end or building a new one, our web development services team has done this across 50+ projects since 2014. For a related browser-API pattern, see our guide to the copy-to-clipboard event using JavaScript.

Frequently Asked Questions

What is the difference between jQuery mouse events and touch events?

Mouse events (click, mousedown, mousemove, hover) respond to a pointing device, while touch events respond to fingers on a screen (touchstart, or jQuery Mobile's tap/swipe). Historically you had to write both to support desktop and mobile. The modern Pointer Events API removes that split by treating mouse, touch, and pen as a single "pointer," so one handler works everywhere.

Should I use Pointer Events instead of jQuery mouse and touch events?

Yes, for new code. The native Pointer Events API (pointerdown, pointermove, pointerup, pointercancel) handles mouse, touch, and stylus with one code path and needs no library. Use jQuery events when maintaining an existing jQuery project where rewriting isn't worth the risk, but reach for Pointer Events for anything new.

Does jQuery have built-in tap and swipe events?

No. jQuery core has no tap, taphold, or swipe events — those belonged to the separate jQuery Mobile plugin, which is deprecated and unmaintained. For new projects, detect taps and swipes yourself by comparing pointer start/end position and elapsed time with Pointer Events, rather than adding jQuery Mobile.

What replaced jQuery's .bind() and .toggle() event methods?

Use .on() and .off() instead of the deprecated .bind()/.unbind(). The event-style .toggle(handler1, handler2) that alternated handlers on each click was deprecated in jQuery 1.8 and removed in 1.9 — track the toggled state yourself inside an .on('click', ...) handler. The animation method $.fn.toggle() for showing and hiding elements still exists and is unrelated.

Why use touch-action and passive event listeners?

The CSS touch-action property tells the browser which native gestures (like scrolling) to keep versus let your code handle, preventing janky conflicts with custom swipes — for example touch-action: pan-y keeps vertical scroll while you handle horizontal. Passive listeners ({ passive: true }) promise you won't call preventDefault(), letting the browser scroll immediately for smoother performance.

How do I convert jQuery event code to vanilla JavaScript?

Replace $('#el').on('click', fn) with el.addEventListener('click', fn), $(document).ready(fn) with a DOMContentLoaded listener, and event delegation like $(document).on('click', '.row', fn) with a single listener that checks e.target.closest('.row'). For pointer interactions, swap parallel mouse/touch handlers for unified Pointer Events. See our guide on event delegation in jQuery for the delegation pattern.

Share this article