jQuery .hover() Method

Beginner
⚠️ Deprecated since 3.3
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Mouse events

What You’ll Learn

The .hover() method is jQuery’s convenience API for binding mouseenter and mouseleave handlers in one call. This tutorial covers .hover(handlerIn, handlerOut) since 1.0, single-function .hover(handlerInOut) since 1.4, migration to .on("mouseenter") and .on("mouseleave"), and why the method is deprecated since jQuery 3.3.

01

handlerIn

Pointer enters

02

handlerOut

Pointer leaves

03

One fn

Since 1.4

04

.on()

Modern bind

05

.off()

Unbind

06

Deprecated

Since 3.3

Introduction

Hover effects are everywhere on the web — menus that drop down when you point at them, buttons that change color, table rows that highlight. jQuery’s .hover() method made this easy: pass one function for when the mouse enters and another for when it leaves, without writing two separate .on() calls.

Under the hood, .hover() is not a separate browser event — it binds mouseenter and mouseleave. Those events behave differently from mouseover and mouseout: they do not re-fire when the pointer moves over child elements inside the bound node. That makes .hover() ideal for stable enter/leave behavior on containers with nested content.

Understanding the .hover() Method

The official jQuery API describes .hover() as a way to bind one or two handlers executed when the mouse pointer enters and leaves matched elements. With two functions, the first runs on enter and the second on leave. With one function (since 1.4), the same callback runs for both — inspect event.type to distinguish "mouseenter" from "mouseleave".

Calling $(selector).hover(handlerIn, handlerOut) is shorthand for:

jQuery
$( selector ).on( "mouseenter", handlerIn ).on( "mouseleave", handlerOut );
⚠️
Deprecated since jQuery 3.3

Do not use .hover() in new code. Replace two-handler form with .on("mouseenter", fnIn).on("mouseleave", fnOut) and single-handler form with .on("mouseenter mouseleave", fn). Legacy code still runs in jQuery 3.x — migrate when you touch those files.

📝 Syntax

The .hover() method has two signatures from the official jQuery API. Both are deprecated since 3.3:

1. Two handlers — .hover( handlerIn, handlerOut ) (since 1.0, deprecated 3.3)

jQuery
.hover( handlerIn, handlerOut )
  • handlerIn — runs when the pointer enters the element.
  • handlerOut — runs when the pointer leaves the element.
  • Modern replacement: .on( "mouseenter", handlerIn ).on( "mouseleave", handlerOut ).

2. Single handler — .hover( handlerInOut ) (since 1.4, deprecated 3.3)

jQuery
.hover( handlerInOut )
  • One function runs for both enter and leave — check event.type inside.
  • Modern replacement: .on( "mouseenter mouseleave", handlerInOut ).

3. Unbind — .off( "mouseenter mouseleave" )

jQuery
$( "td" ).off( "mouseenter mouseleave" );
  • There is no separate "hover" event name — unbind the underlying mouseenter/mouseleave handlers.

Return value

  • .hover() returns the original jQuery object for chaining.

⚡ Quick Reference

GoalLegacy (.hover)Modern replacement
Enter + leave handlers$("#box").hover(fnIn, fnOut)$("#box").on("mouseenter", fnIn).on("mouseleave", fnOut)
Single handler both ways$("#box").hover(fn)$("#box").on("mouseenter mouseleave", fn)
Add class on hover.hover(function(){ $(this).addClass("hover"); }, function(){ $(this).removeClass("hover"); })
Remove hover handlers$("#box").off("mouseenter mouseleave")
Delegated hover on children$("#menu").on("mouseenter", "li", fnIn).on("mouseleave", "li", fnOut)

📋 .hover() vs mouseenter / mouseleave vs mouseover

Four related concepts — know what .hover() wraps and when to prefer mouseenter over mouseover.

.hover()
deprecated

Shorthand for mouseenter + mouseleave in one call — migrate to .on()

mouseenter
enter

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

mouseleave
leave

Fires once when pointer exits element entirely

mouseover
bubbles

Re-fires on every child boundary — use mouseenter for stable hover

Examples Gallery

Examples 1–4 follow the official jQuery API documentation. Example 5 covers migration to .on(). Move your pointer over the demo areas in each Try-it lab. Remember: .hover() is deprecated — these demos show legacy syntax you will encounter in older code.

📚 Two-Handler Pattern

Official jQuery demos with separate enter and leave callbacks.

Example 1 — Official Demo: Append Markers on List Hover

Add a red *** marker when the pointer enters a list item; remove it on leave. Items with class fade also pulse with fadeOut / fadeIn.

jQuery
$( "li" ).hover(
  function() {
    $( this ).append( $( "<span> ***</span>" ) );
  },
  function() {
    $( this ).find( "span" ).last().remove();
  }
);

$( "li.fade" ).hover( function() {
  $( this ).fadeOut( 100 );
  $( this ).fadeIn( 500 );
} );
Try It Yourself

How It Works

The two-function .hover(fnIn, fnOut) form runs the first callback on mouseenter and the second on mouseleave. A second .hover(singleFn) on li.fade stacks an additional enter-only animation — the single-function form runs the same handler for both events, but here only the enter animation is noticeable.

Example 2 — Official Demo: Highlight Table Cells on Hover

Add a hover class when the pointer enters a cell; remove it on leave.

jQuery
$( "td" ).hover(
  function() {
    $( this ).addClass( "hover" );
  },
  function() {
    $( this ).removeClass( "hover" );
  }
);
Try It Yourself

How It Works

This is the most common .hover() pattern in legacy code: toggle a CSS class on enter and remove it on leave. The modern equivalent uses .on("mouseenter") and .on("mouseleave") with the same callbacks.

Example 3 — Official Demo: Unbind with .off()

Remove hover behavior from table cells — there is no "hover" event to unbind.

jQuery
$( "td" ).off( "mouseenter mouseleave" );
Try It Yourself

How It Works

.hover() registers handlers as mouseenter and mouseleave — not under a fictional "hover" event name. Pass both event strings to .off() to remove all enter/leave handlers from the matched cells.

📈 Single Handler & Migration

One-function hover and modern .on() replacement.

Example 4 — Official Demo: Single Handler Toggles Next Sibling

One function handles both enter and leave — toggle active class and slide the next li (official 1.4 demo pattern).

jQuery
$( "li" )
  .odd()
  .hide()
  .end()
  .even()
  .hover( function() {
    $( this )
      .toggleClass( "active" )
      .next()
      .stop( true, true )
      .slideToggle();
  } );
Try It Yourself

How It Works

When you pass one function to .hover(), jQuery binds it to both mouseenter and mouseleave. Using .toggleClass() and .slideToggle() inside means the same action reverses on leave — a compact pattern for accordion-style hover menus.

Example 5 — Migration: .hover(fnIn, fnOut) vs .on("mouseenter") / .on("mouseleave")

Both bind the same enter/leave behavior — .on() is the recommended API for new code.

jQuery
$( "#legacy" ).hover(
  function() {
    $( "#out" ).text( "Legacy: .hover(fnIn, fnOut) — deprecated since jQuery 3.3." );
  },
  function() {
    $( "#out" ).text( "Legacy: pointer left #legacy." );
  }
);

$( "#modern" ).on( "mouseenter", function() {
  $( "#out" ).text( "Modern: .on('mouseenter') — use this for new code." );
} ).on( "mouseleave", function() {
  $( "#out" ).text( "Modern: .on('mouseleave') — pointer left #modern." );
} );
Try It Yourself

How It Works

Under the hood, .hover(fnIn, fnOut) is exactly .on("mouseenter", fnIn).on("mouseleave", fnOut). Migration is a straight rename with no behavior change. Chaining two .on() calls keeps the same readability as one .hover() call.

🚀 Common Use Cases

  • Navigation menus — show dropdown on enter, hide on leave — classic .hover(fnIn, fnOut) pattern.
  • Table row highlight — add/remove a CSS class on td or tr hover for spreadsheet UIs.
  • Tooltip preview — append or show a tooltip element on enter, remove on leave.
  • Image swap — change src on enter, restore on leave for product galleries.
  • Accordion details — single-function .hover(fn) with .slideToggle() on adjacent rows.
  • Reading legacy code — recognize .hover() as mouseenter + mouseleave when maintaining older jQuery projects.

🧠 How .hover() Routes Through jQuery

1

You call .hover()

One function → bind to both mouseenter and mouseleave. Two functions → first is enter, second is leave.

dispatch
2

mouseenter fires

Pointer enters the element boundary — handlerIn (or handlerInOut with event.type === "mouseenter") runs.

enter
3

mouseleave fires

Pointer exits the element entirely — handlerOut runs. Moving over children does not re-trigger enter.

leave
4

jQuery object returned

Chain further methods — .hover(fnIn, fnOut).addClass("ready") works like separate .on() calls.

📝 Notes

  • Deprecated since jQuery 3.3 — use .on("mouseenter", fnIn).on("mouseleave", fnOut) in new code.
  • Two-handler form since jQuery 1.0; single-handler form since 1.4.
  • There is no "hover" event — unbind with .off("mouseenter mouseleave").
  • mouseenter / mouseleave do not bubble from children — stable for containers with nested elements.
  • Prefer CSS :hover for pure styling; use JavaScript hover handlers for DOM changes and animations.
  • Touch devices have no true hover — provide click/tap alternatives for mobile users.
  • Do not confuse .hover() with the removed .live() or browser mouseover — each behaves differently.

Browser Support

The underlying mouseenter and mouseleave events are supported in every browser jQuery targets. The .hover() method itself is a jQuery API — it works in jQuery 1.x, 2.x, and 3.x. Binding via .hover() is deprecated since 3.3 but still functional.

jQuery 1.0+

jQuery .hover() method

Supported across all jQuery versions you are likely to maintain. Deprecated since 3.3 — use .on('mouseenter') and .on('mouseleave') for new projects. Native equivalents: element.addEventListener('mouseenter', fn) and addEventListener('mouseleave', fn).

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
.hover() Legacy API

Bottom line: Safe in legacy jQuery projects. Migrate to .on('mouseenter') / .on('mouseleave') when updating code. Test touch devices separately — hover has no mobile equivalent.

Conclusion

The jQuery .hover() method is the legacy shorthand for binding mouseenter and mouseleave handlers. Use .hover(handlerIn, handlerOut) for separate enter/leave callbacks, or .hover(handlerInOut) when one function handles both — both forms deprecated since jQuery 3.3.

For new code, prefer .on("mouseenter", fnIn).on("mouseleave", fnOut) or .on("mouseenter mouseleave", fn). Unbind with .off("mouseenter mouseleave"). When you encounter .hover() in older projects, recognize it, understand it, and migrate when practical.

💡 Best Practices

✅ Do

  • Use .on("mouseenter", fnIn).on("mouseleave", fnOut) for new hover bindings
  • Prefer CSS :hover when only colors or visibility change
  • Use mouseenter / mouseleave instead of mouseover / mouseout for stable hover
  • Call .off("mouseenter mouseleave") when removing hover behavior
  • Provide tap/click fallbacks for touch devices

❌ Don’t

  • Write new code with deprecated .hover()
  • Try to unbind with .off("hover") — that event name does not exist
  • Use mouseover when you mean enter-once behavior — it re-fires on children
  • Rely on hover alone for critical UI on mobile
  • Stack many .hover() calls without understanding handler order

Key Takeaways

Knowledge Unlocked

Six things to remember about .hover()

Enter, leave, migrate.

6
Core concepts
fn 02

.hover(fn)

Since 1.4

Single
enter 03

mouseenter

Under hood

Event
leave 04

mouseleave

Under hood

Event
.on 05

.on()

Modern

Replace
3.3 06

Deprecated

Since 3.3

Migrate

❓ Frequently Asked Questions

The .hover() method binds handlers for mouseenter and mouseleave in one call. With two functions — .hover(handlerIn, handlerOut) — handlerIn runs when the pointer enters the element and handlerOut when it leaves. With one function since jQuery 1.4 — .hover(handlerInOut) — the same function runs for both events; check event.type inside. Deprecated since 3.3.
Yes — both .hover(handlerIn, handlerOut) and .hover(handlerInOut) are deprecated since jQuery 3.3. Use .on('mouseenter', handlerIn).on('mouseleave', handlerOut) for two handlers, or .on('mouseenter mouseleave', handlerInOut) for one. Existing legacy code still runs in jQuery 3.x; migrate when you refactor those files.
CSS :hover is a stylesheet pseudo-class — no JavaScript required for simple color or visibility changes. jQuery .hover() runs JavaScript callbacks on mouseenter and mouseleave — useful for DOM changes, animations, and logic CSS cannot express. For pure styling, prefer CSS; for behavior, use .on('mouseenter') and .on('mouseleave') in modern code.
.hover() is shorthand for mouseenter + mouseleave. mouseenter fires when the pointer enters an element and does not re-fire when moving over child elements inside it. mouseover bubbles and re-fires on every child boundary crossing. For typical hover menus and highlights, mouseenter/mouseleave (via .hover() or .on()) are the right choice.
Use .off('mouseenter mouseleave') on the same selector — .hover() registers under those event names, not a separate 'hover' event. Example: $('td').off('mouseenter mouseleave') removes handlers bound by the official table-cell hover demo.
Replace .hover(fnIn, fnOut) with .on('mouseenter', fnIn).on('mouseleave', fnOut). Replace .hover(fn) with .on('mouseenter mouseleave', fn). Under the hood, .hover() already delegates to those events — migration is a straight rename with no behavior change for simple bindings.
Did you know?

jQuery’s .hover() never introduced a browser "hover" event — it always mapped to mouseenter and mouseleave. That is why unbinding requires .off("mouseenter mouseleave"), as documented in the official API Example 3. The method was deprecated in 3.3 alongside other event shorthands like .click(handler), steering developers toward the unified .on() API from jQuery 1.7.

Next: mousedown Event

Learn when to react on mouse button press — before release.

mousedown 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