jQuery mousemove Event

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Mouse events

What You’ll Learn

The mousemove event fires whenever the pointer moves inside an element. This tutorial covers binding with .on("mousemove"), reading coordinates with event.pageX and event.pageY, triggering with .trigger("mousemove"), performance tips for high-frequency handlers, and the drag pattern that binds on mousedown and unbinds on mouseup.

01

.on()

Bind handler

02

pageX/Y

Coordinates

03

.trigger()

Fire mousemove

04

Performance

High frequency

05

Drag pattern

Bind & unbind

06

Since 1.7

Modern API

Introduction

Most mouse events fire once per user action — a click, a press, an enter. mousemove is different: it fires continuously while the pointer moves inside an element, sometimes hundreds of times per second. That makes it essential for drag-and-drop, drawing tools, custom sliders, live coordinate displays, and any UI that must follow the cursor.

The official jQuery API distinguishes the mousemove event (bound with .on("mousemove") since 1.7) from the deprecated .mousemove() method used in older code. To programmatically fire a handler, use .trigger("mousemove") — available since jQuery 1.0. Any HTML element can receive the mousemove event.

Understanding the mousemove Event

The mousemove event is sent to an element when the mouse pointer moves inside that element. jQuery normalizes coordinate properties — especially event.pageX and event.pageY — so you can read pointer position consistently across browsers.

Because the event fires on every pixel of movement, handlers must stay lightweight. The official jQuery documentation recommends binding mousemove only when needed — often from a mousedown handler — and unbinding it from a mouseup handler attached high in the DOM tree (such as document), since release may occur outside the original element.

💡
Beginner Tip

Do not leave a permanent mousemove handler on document unless you truly need global tracking. For drag operations, bind on press, track during move, and unbind on release — this keeps your page responsive.

📝 Syntax

The modern jQuery API for the mousemove event has two main forms — binding a handler and triggering the event:

1. Bind a handler — .on("mousemove" [, eventData ], handler) (since 1.7)

jQuery
.on( "mousemove" [, eventData ], handler )
  • eventData — optional object passed to the handler as event.data.
  • handler — function called on each move: function( event ) { ... }.

2. Event delegation — .on("mousemove", selector, handler)

jQuery
$( "#canvas" ).on( "mousemove", ".handle", function( event ) {
  // runs when pointer moves over any .handle inside #canvas
} );

3. Trigger the event — .trigger("mousemove") (since 1.0)

jQuery
.trigger( "mousemove" )
  • Runs bound mousemove handlers on the matched element(s).
  • Programmatic triggers may leave event.pageX and event.pageY undefined unless you supply coordinates.
  • Use .triggerHandler("mousemove") to run handlers without bubbling or default actions.

4. Unbind — .off("mousemove" [, selector] [, handler])

jQuery
$( "#target" ).off( "mousemove" );              // remove all mousemove handlers
$( "#canvas" ).off( "mousemove", ".handle", fn ); // remove delegated handler

Official jQuery API examples

jQuery
$( "#target" ).on( "mousemove", function( event ) {
  var msg = "Handler for `mousemove` called at ";
  msg += event.pageX + ", " + event.pageY;
  $( "#log" ).append( "<p>" + msg + "</p>" );
} );

$( "#other" ).on( "click", function() {
  $( "#target" ).trigger( "mousemove" );
} );

Return value

  • .on() and .trigger() return the original jQuery object for chaining.
  • Handler return values are ignored unless you use return false (equivalent to preventDefault() + stopPropagation()).

⚡ Quick Reference

GoalCode
Bind mousemove handler$("#box").on("mousemove", fn)
Read document coordinatesevent.pageX + ", " + event.pageY
Read viewport coordinatesevent.clientX + ", " + event.clientY
Pass data to handler$("#box").on("mousemove", { id: 1 }, fn)
Trigger mousemove programmatically$("#target").trigger("mousemove")
Drag pattern: bind on press$("#box").on("mousedown", function(){ $(document).on("mousemove", drag); })
Drag pattern: unbind on release$(document).one("mouseup", function(){ $(document).off("mousemove", drag); })
Remove mousemove handlers$("#box").off("mousemove")

📋 mousemove vs mouseover vs mouseenter vs deprecated .mousemove()

Four related pointer events — choose the one that matches how often and when you need to respond.

mousemove
continuous

Fires on every pointer movement inside the element — high frequency

mouseover
enter+bubble

Fires when pointer enters element or child — bubbles up the tree

mouseenter
enter once

Fires once when pointer enters — no re-fire on child crossings

.mousemove() method
deprecated

Old binding shorthand — use .on("mousemove") instead

Examples Gallery

Examples 1–3 follow the official jQuery API documentation. Examples 4–5 cover the drag bind/unbind pattern and live coordinate tracking. Use the Try-it links to run each snippet in the browser.

📚 Binding & Triggering

Official jQuery demos for mousemove handlers and programmatic triggers.

Example 1 — Official Demo: Log Coordinates on #target

Append a message with event.pageX and event.pageY each time the pointer moves over the target — the canonical .on("mousemove") pattern.

jQuery
$( "#target" ).on( "mousemove", function( event ) {
  var msg = "Handler for `mousemove` called at ";
  msg += event.pageX + ", " + event.pageY;
  $( "#log" ).append( "<p>" + msg + "</p>" );
} );
Try It Yourself

How It Works

.on("mousemove", fn) registers the function on the element. jQuery calls it on every pointer movement inside the element boundary. event.pageX and event.pageY are normalized by jQuery for cross-browser consistency.

Example 2 — Official Demo: #other Triggers mousemove on #target

One element programmatically fires the mousemove handler on another — note the official API shows coordinates as undefined when triggered without a real pointer position.

jQuery
$( "#target" ).on( "mousemove", function( event ) {
  var msg = "Handler for `mousemove` called at ";
  msg += event.pageX + ", " + event.pageY;
  $( "#log" ).append( "<p>" + msg + "</p>" );
} );

$( "#other" ).on( "click", function() {
  $( "#target" ).trigger( "mousemove" );
} );
Try It Yourself

How It Works

.trigger("mousemove") synthetically fires the event on #target, running bound handlers. Without a real mouse event, coordinate properties may be undefined — pass a custom event object if your handler requires specific values.

Example 3 — Official Demo: pageX/pageY vs clientX/clientY

Show both coordinate systems when the pointer moves over a yellow div — adapted from the official jQuery API demo.

jQuery
$( "div" ).on( "mousemove", function( event ) {
  var pageCoords = "( " + event.pageX + ", " + event.pageY + " )";
  var clientCoords = "( " + event.clientX + ", " + event.clientY + " )";
  $( "span" ).first().text( "( event.pageX, event.pageY ) : " + pageCoords );
  $( "span" ).last().text( "( event.clientX, event.clientY ) : " + clientCoords );
} );
Try It Yourself

How It Works

pageX/pageY measure from the document origin; clientX/clientY measure from the viewport. jQuery normalizes pageX and pageY across browsers — use them when positioning elements relative to the full page.

📈 Performance & Drag Patterns

Patterns from the official API notes — bind only during drag and unbind when done.

Example 4 — Bind on mousedown, Unbind on mouseup (Drag Pattern)

Track pointer movement only while the user is dragging — the official API’s recommended optimization for mousemove handlers.

jQuery
function onMove( event ) {
  $( "#box" ).css( { left: event.pageX - 25, top: event.pageY - 25 } );
}

$( "#box" ).on( "mousedown", function( event ) {
  if ( event.which !== 1 ) return;
  $( document ).on( "mousemove", onMove );
  $( document ).one( "mouseup", function() {
    $( document ).off( "mousemove", onMove );
  } );
} );
Try It Yourself

How It Works

Binding mousemove permanently would waste CPU. Instead, bind on mousedown, attach mousemove to document for global tracking, and use $(document).one("mouseup", ...) to unbind — even if the user releases outside the original element.

Example 5 — Live Coordinate Display Inside a Zone

Show real-time X/Y coordinates and a crosshair marker that follows the pointer — a practical pattern for image maps, drawing previews, and debug overlays.

jQuery
var $zone = $( "#zone" );
var $marker = $( "#marker" );
var $readout = $( "#readout" );

$zone.on( "mousemove", function( event ) {
  var offset = $zone.offset();
  var x = event.pageX - offset.left;
  var y = event.pageY - offset.top;
  $marker.css( { left: x - 6, top: y - 6 } );
  $readout.text( "Local: " + Math.round( x ) + ", " + Math.round( y ) );
} );

$zone.on( "mouseleave", function() {
  $readout.text( "Move pointer inside the zone" );
} );
Try It Yourself

How It Works

event.pageX minus $zone.offset().left converts document coordinates to coordinates relative to the element’s top-left corner. Pairing with mouseleave resets the UI when the pointer exits the tracking area.

🚀 Common Use Cases

  • Drag-and-drop — bind mousemove on document during mousedown, unbind on mouseup.
  • Drawing tools — track pointer on canvas during stroke: mousedown start, mousemove draw, mouseup finish.
  • Custom sliders — update thumb position from event.pageX while dragging.
  • Image map previews — show local X/Y over a photo or diagram on mousemove.
  • Tooltip positioning — move a tooltip near the cursor using page coordinates.
  • Debug overlays — display live coordinate readouts during development.

🧠 How the mousemove Event Fits a Drag Gesture

1

Pointer over element

User moves cursor inside the target — no mousemove handler needed yet unless you want permanent tracking.

ready
2

Button pressed

User presses mouse button — mousedown fires. Bind mousemove on document to start tracking.

mousedown
3

Pointer moves

User drags — mousemove fires continuously. Read event.pageX/event.pageY and update position.

mousemove
4

Button released

mouseup fires — often on document. Unbind mousemove to stop tracking and free browser resources.

📝 Notes

  • Bind with .on("mousemove", handler) since jQuery 1.7 — not the deprecated .mousemove(handler) method.
  • Trigger with .trigger("mousemove") since jQuery 1.0 — coordinates may be undefined without a real pointer event.
  • mousemove fires on every pixel of movement — keep handlers fast and unbind when done.
  • jQuery normalizes event.pageX and event.pageY for cross-browser use.
  • Bind mouseup on document when tracking drags — release may occur outside the original element.
  • Any HTML element can receive mousemove — not limited to <canvas> or interactive widgets.
  • Use .off("mousemove") to remove handlers — avoid deprecated .unbind("mousemove").
  • For enter/leave hover effects without continuous tracking, prefer mouseenter and mouseleave over mousemove.

Browser Support

The mousemove event is a standard DOM event supported in every browser jQuery targets. jQuery’s .on("mousemove") (since 1.7) and .trigger("mousemove") (since 1.0) normalize cross-browser behavior — including event.pageX and event.pageY coordinates.

jQuery 1.7+

jQuery mousemove event

Supported in jQuery 1.x, 2.x, and 3.x across all modern browsers and IE with supported jQuery versions. Native equivalent: element.addEventListener('mousemove', fn) — jQuery adds collection binding, eventData, delegation, and .trigger() in one chainable API.

100% With jQuery loaded
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
mousemove Universal

Bottom line: Safe in any jQuery project. Prefer .on('mousemove') over deprecated .mousemove() for binding. Optimize handlers — unbind when tracking is no longer needed.

Conclusion

The jQuery mousemove event fires continuously while the pointer moves inside an element. Bind handlers with .on("mousemove", fn), read coordinates with event.pageX and event.pageY, and fire handlers programmatically with .trigger("mousemove").

Because mousemove is high-frequency, keep handlers lightweight and unbind them when tracking ends — especially in drag patterns that bind on mousedown and unbind on mouseup. For simple hover styling, use CSS or mouseenter/mouseleave instead of permanent mousemove listeners.

💡 Best Practices

✅ Do

  • Bind with .on("mousemove", handler) — the modern, delegation-capable API
  • Use event.pageX and event.pageY for document-relative positioning
  • Bind mousemove only during drag — from mousedown, unbind on document mouseup
  • Keep handler logic minimal — defer heavy work with requestAnimationFrame if needed
  • Call .off("mousemove") when removing elements or tearing down handlers

❌ Don’t

  • Use deprecated .mousemove(handler) for new code — use .on("mousemove")
  • Leave permanent mousemove on document without a clear need
  • Perform expensive DOM reflows on every mousemove event
  • Bind mouseup only on the drag source — release may happen elsewhere
  • Assume .trigger("mousemove") includes real pointer coordinates

Key Takeaways

Knowledge Unlocked

Six things to remember about the mousemove event

Track, optimize, unbind.

6
Core concepts
XY 02

pageX/pageY

Coords

Position
03

.trigger()

Fire

Programmatic
04

High frequency

Performance

Optimize
drag 05

Bind/unbind

Pattern

Drag
.off 06

.off("mousemove")

Cleanup

Unbind

❓ Frequently Asked Questions

The mousemove event fires whenever the mouse pointer moves while it is inside an element — even by a single pixel. In modern jQuery, bind handlers with .on('mousemove', handler) since version 1.7. Any HTML element can receive this event. It is one of the highest-frequency browser events, so handlers should stay lightweight.
event.pageX and event.pageY give coordinates relative to the top-left corner of the entire document (including scrolled content). event.clientX and event.clientY are relative to the browser viewport (the visible window). jQuery normalizes pageX and pageY so they work consistently across browsers. Use pageX/pageY when positioning elements on the page; use clientX/clientY when you care about viewport position.
mousemove can fire hundreds of times per second during even a small hand movement. If your handler does heavy DOM updates, layout calculations, or runs multiple times per frame, it can slow the browser noticeably. Keep handlers fast, throttle or requestAnimationFrame updates when possible, and unbind mousemove as soon as you no longer need it — especially after drag operations end.
A common pattern from the official jQuery API: bind mousemove inside a mousedown handler, then unbind it from a mouseup handler. Because mouseup may fire on a different element than mousemove, attach the mouseup handler high in the DOM tree — typically $(document).on('mouseup', fn) or $(document).one('mouseup', fn).
Call .trigger('mousemove') on the target element: $('#target').trigger('mousemove'). Available since jQuery 1.0, trigger runs bound mousemove handlers. Note that programmatic triggers do not include real pointer coordinates — event.pageX and event.pageY may be undefined unless you pass them via a custom event object.
Use .on('mousemove', handler) for binding. The old .mousemove(handler) shorthand still works but is deprecated since jQuery 3.3 — it wraps .on('mousemove'). For unbinding, use .off('mousemove') instead of .unbind('mousemove'). .on() also supports event delegation: .on('mousemove', '.handle', fn).
Did you know?

The official jQuery API warns that mousemove can fire hundreds of times during a very small hand movement. If your handler does significant processing — or if multiple handlers exist for the same event — it can become a serious performance drain. That is why drag libraries bind mousemove only after mousedown and unbind it on mouseup, rather than listening globally at all times.

Next: .mousemove() Method

Learn the deprecated shorthand — and how to migrate to .on("mousemove").

.mousemove() tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful