Himanshu SharmaSoftware engineer
Let’s talk

jQuery · Lesson 23 of 45

Mouse events and hover

Handle click, dblclick, mouseenter, mouseleave, mouseover and mousemove with jQuery, see why mouseenter beats mouseover, and build hover effects.

11 minEventsUpdated 23 October 2026

By the end of this lessonReact to clicks and pointer movement, choose the right hover events, and keep hover-only features usable on touch screens and keyboards.

Clicks

click is the event you will use most. Use it on buttons and links: browsers also fire click when a focused button is activated with Enter or Space, so keyboard users get the same behaviour for free.

html
<button id="one">Real button</button>
<div id="two" style="display:inline-block; padding: 4px 8px; border: 1px solid">Clickable div</div>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#one, #two").on("click", function () {
    console.log("clicked", this.id);
  });
</script>
result
clicked one
clicked two

Both respond to a mouse click, but only the real <button> can be reached with the Tab key and activated with the keyboard. If you must make a div clickable, add tabindex="0", role="button" and a keydown handler for Enter and Space. Using a <button> is far simpler.

dblclick fires on a double-click. It is rare on the web and has no keyboard equivalent, so avoid putting important actions behind it.

Entering and leaving

mouseenter fires when the pointer moves onto an element; mouseleave when it moves off:

html
<style>
  #tile { width: 220px; padding: 16px; background: #f1f5f9; transition: background .2s; }
  #tile.over { background: #fde68a; }
</style>
<div id="tile">Hover over this tile<p>It has a paragraph inside.</p></div>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#tile")
    .on("mouseenter", function () { $(this).addClass("over"); console.log("enter"); })
    .on("mouseleave", function () { $(this).removeClass("over"); console.log("leave"); });
</script>
result
enter

The output shows a single enter (the example simulates the pointer arriving). Move your own mouse in and out of the tile in the editor to see leave too.

Why mouseover flickers

There is an older pair, mouseover and mouseout. The difference matters when the element has children:

  • mouseenter/mouseleave fire once for the element. Moving between its children does nothing.
  • mouseover/mouseout bubble: they fire again every time the pointer moves onto or off a child, and the parent's handler hears them.
html
<ul id="menu" style="padding: 8px 24px; background: #f1f5f9">
  <li>Home</li>
  <li>Shop</li>
</ul>
<button id="report">Report</button>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  let enters = 0, overs = 0;
  $("#menu")
    .on("mouseenter", () => enters++)
    .on("mouseover", () => overs++);

  $("#report").on("click", () => console.log("mouseenter fired", enters, "time(s); mouseover fired", overs, "time(s)"));
</script>
result
mouseenter fired 1 time(s); mouseover fired 3 time(s)

The pointer entered the menu and then moved over its two items, and the Report button printed the counts. mouseenter fired once, but mouseover fired for the menu and again for each item. If your mouseover handler toggled a dropdown, it would flicker as the user moved across the items. Use mouseenter and mouseleave for hover effects.

The .hover() shorthand

You will see .hover(overFn, outFn) in older code. It attaches the first function to mouseenter and the second to mouseleave:

javascript
$(".card").hover(
  function () { $(this).addClass("raised"); },
  function () { $(this).removeClass("raised"); }
);

It still works in jQuery 4 but is deprecated. The modern equivalent is two .on() calls, as in the tile example.

Following the pointer

mousemove fires many times a second as the pointer moves. The event object gives the position:

html
<div id="pad" style="height: 120px; background: #ecfeff; border: 1px dashed #06b6d4">Move the mouse here</div>
<p id="pos">x: -, y: -</p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#pad").on("mousemove", function (event) {
    const box = $(this).offset();
    const x = Math.round(event.pageX - box.left);
    const y = Math.round(event.pageY - box.top);
    $("#pos").text("x: " + x + ", y: " + y);
  });
</script>

Subtracting the element's .offset() from event.pageX and pageY gives the position inside the element. Keep mousemove handlers tiny, because they run constantly.

Hover is not enough on its own

Touch screens have no hover, and keyboard users move between elements with Tab. A feature that only appears on hover, such as a dropdown menu or a delete button, is invisible to them. Pair hover with something else:

  • show the same thing on focus (or use CSS :focus-within) so keyboard users get it;
  • make it open on click as well, so touch users can tap;
  • or simply show the control all the time on small screens.

For purely visual effects (a shadow, a colour change), CSS :hover is simpler than jQuery and needs no JavaScript at all.

Common mistakes

  • Using mouseover/mouseout for hover effects on elements with children.
  • Making div elements clickable instead of using buttons and links.
  • Hiding essential features behind hover.
  • Doing heavy work in mousemove, such as rebuilding HTML on every event.

Exercise

Make an image placeholder (a coloured div) that shows a caption when the pointer enters and hides it when the pointer leaves. Also show the caption when the div receives keyboard focus.

Show one possible answer
html
<div id="photo" tabindex="0" style="width: 200px; height: 100px; background: #c7d2fe"></div>
<p id="caption" hidden>Sunrise over the lake</p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("#photo")
    .on("mouseenter focus", () => $("#caption").prop("hidden", false))
    .on("mouseleave blur", () => $("#caption").prop("hidden", true));
</script>
result
Sunrise over the lake

Key points

  • click and dblclick fire on clicks; click also fires when a focused button or link is activated with the keyboard.
  • mouseenter and mouseleave fire once when the pointer enters or leaves an element, ignoring its children.
  • mouseover and mouseout also fire when moving between child elements, which often causes flicker.
  • Do not hide important features behind hover alone; touch screens and keyboards have no hover.

Check yourself

1. Which pair fires only once as the pointer enters and leaves a card, even if it has child elements?
2. Does a click event fire when a user presses Enter on a focused button?
3. What does .hover(over, out) do?
4. Why is it risky to show a menu only on hover?