The mouseover event fires when the mouse pointer enters an element. This tutorial covers binding with .on("mouseover"), triggering with .trigger("mouseover"), understanding bubbling and event.relatedTarget, comparing mouseover with mouseenter, and when to prefer mouseenter for nested menus.
01
.on()
Bind handler
02
.trigger()
Fire over
03
bubbles
Child crosses
04
relatedTarget
Filter false
05
mouseout
Legacy pair
06
Since 1.7
Modern API
Fundamentals
Introduction
Every hover interaction has an entry — dropdowns open, tooltips appear, and highlight classes are added when the pointer enters. jQuery’s mouseover event is the classic way to run JavaScript at that moment, but its bubbling behavior can surprise developers working with nested elements.
The official jQuery API distinguishes the mouseoverevent (bound with .on("mouseover") since 1.7) from the deprecated .mouseover()method used in older code. Unlike mouseenter, mouseover bubbles — it fires when entering the bound element or when moving from the parent into a child inside it. To programmatically fire a handler, use .trigger("mouseover") — available since jQuery 1.0.
Concept
Understanding the mouseover Event
The mouseover event is sent to an element when the mouse pointer enters that element. Because it bubbles, moving from a parent into a child inside the bound element also triggers mouseover on the parent — the event trickles up the DOM tree just like a physical entry on every child boundary.
This bubbling behavior causes headaches with nested menus and tooltips. When the pointer moves from a menu item into its submenu, mouseover fires on the parent container again — making it look like the user entered the menu from outside. For nested content, jQuery recommends mouseenter paired with mouseleave instead. If you must use mouseover, inspect event.relatedTarget to filter false positives.
💡
Beginner Tip
For hover menus with submenus, prefer mouseenter + mouseleave over mouseover + mouseout. If you inherit legacy mouseover code on nested elements, check event.relatedTarget — when the pointer came from inside the bound container, ignore the event.
Foundation
📝 Syntax
The modern jQuery API for the mouseover event has two main forms — binding a handler and triggering the event:
.on() and .trigger() return the original jQuery object for chaining.
Handler return values are ignored unless you use return false (equivalent to preventDefault() + stopPropagation()).
Cheat Sheet
⚡ Quick Reference
Goal
Code
Bind mouseover handler
$("#box").on("mouseover", fn)
Pair over and out (legacy)
.on("mouseover", show).on("mouseout", hide)
Filter child crossings
if ($(event.relatedTarget).closest("#outer").length) return;
Delegated mouseover on children
$("#menu").on("mouseover", "li", fn)
Trigger mouseover programmatically
$("#outer").trigger("mouseover")
Prefer for nested menus
$("#nav").on("mouseenter", fn) instead of mouseover
Remove mouseover handlers
$("#box").off("mouseover")
Compare
📋 mouseover vs mouseenter vs mouseout vs CSS :hover
Four ways to respond when the pointer enters or moves over elements — choose the event that matches your hover needs.
mouseover
bubbles
Re-fires on every child boundary crossing — legacy hover pair with mouseout; filter with relatedTarget
mouseenter
enter once
Fires only when pointer enters bound element from outside — recommended for nested menus and tooltips
mouseout
bubbles
Exit counterpart to mouseover — pair for legacy hover; prefer mouseleave for nested content
CSS :hover
style only
Stylesheet pseudo-class — no JavaScript; use for simple color or visibility changes
Hands-On
Examples Gallery
Examples 1–3 follow the official jQuery API documentation. Examples 4–5 cover event.relatedTarget filtering and the legacy mouseover + mouseout hover pair. Use the Try-it links to run each snippet in the browser.
📚 Binding & Triggering
Official jQuery demos for mouseover handlers and programmatic triggers.
Example 1 — Official Demo: Bind Handler on #outer
Append a log message when the pointer enters the outer element — the canonical .on("mouseover") pattern. Note: the handler also fires when moving into the Inner child (bubbles).
Pointer enters #outer → #log appends: "Handler for mouseover called."
Moving from Outer into Inner child → handler ALSO fires (bubbles)
mouseover fires when entering element OR crossing into a child
How It Works
.on("mouseover", fn) registers the function on #outer. jQuery calls it when the pointer crosses into the outer boundary and when moving from the outer area into the inner child — that bubbling behavior is the key difference from mouseenter.
Example 2 — Official Demo: #other Triggers mouseover on #outer
One element programmatically fires the mouseover handler on another.
Enter #outer → log message appended
Click #other → $("#outer").trigger("mouseover") → same log message
Programmatic trigger invokes bound handlers
How It Works
.trigger("mouseover") synthetically fires the mouseover event on #outer, running the same handler as a physical pointer entry. Useful for testing show behavior or keyboard-accessible fallbacks.
Example 3 — Official Demo: mouseover vs mouseenter
Side-by-side comparison from the mouseover perspective — the left box re-fires on every child boundary crossing; the right box does not.
jQuery
var i = 0;
$( "div.overout" )
.on( "mouseover", function() {
i += 1;
$( this ).find( "span" ).first().text( "mouse over x " + i );
} )
.on( "mouseout", function() {
$( this ).find( "span" ).first().text( "mouse out" );
} );
var n = 0;
$( "div.enterleave" )
.on( "mouseenter", function() {
n += 1;
$( this ).find( "span" ).first().text( "mouse enter x " + n );
} )
.on( "mouseleave", function() {
$( this ).find( "span" ).first().text( "mouse leave" );
} );
Left box (mouseover): enter counter increments when entering outer AND inner child
Right box (mouseenter): enter counter increments only when entering outer boundary
Move between outer and inner on left → count jumps; on right → stable
How It Works
The official API demo uses nested divs with an inner yellow child. mouseover on the left box bubbles — crossing into the inner div counts as a new entry event on the parent. mouseenter on the right ignores child crossings — the counter increments only when the pointer enters the entire outer box from outside. For nested menus, choose the right box pattern.
📈 Filtering & Legacy Hover Pairs
Practical patterns for taming mouseover bubbling and legacy over/out hover code.
Example 4 — Filter with event.relatedTarget
Ignore mouseover events where the pointer came from a child still inside the bound container — reduces false positives without switching events.
jQuery
$( "#outer" ).on( "mouseover", function( event ) {
if ( $( event.relatedTarget ).closest( "#outer" ).length ) {
return; // pointer came from inside #outer
}
$( "#log" ).append( " Entered #outer from outside." );
} );
Move from Outer into Inner → relatedTarget is inside #outer → handler returns early
Enter #outer from outside → relatedTarget is outside → log appends "Entered #outer from outside."
Filters bubbling false positives on nested content
How It Works
event.relatedTarget tells you where the pointer came from. Wrapping it with $(event.relatedTarget).closest("#outer") checks whether the origin is still inside the bound container. If so, the user has not truly entered from outside — skip the handler. This is the standard workaround when you cannot migrate to mouseenter.
Example 5 — Legacy Hover: mouseover + mouseout on Cards
Add highlight on over, remove on out — the classic pre-mouseenter hover pair. Works on flat cards; beware nested content inside each card.
Enter a .card → .highlight class added (mouseover)
Leave the card → .highlight removed (mouseout)
Nested caveat: moving between child elements inside a card re-fires mouseout/mouseover — use mouseenter/mouseleave or relatedTarget filter instead
How It Works
mouseover handles the show half; mouseout handles the hide half. On simple flat cards without nested children, this pair works fine. When cards contain buttons, icons, or nested spans, moving between those children triggers spurious out/over events — migrate to mouseenter + mouseleave for stable behavior.
Applications
🚀 Common Use Cases
Legacy hover pairs — maintain existing mouseover / mouseout code on flat elements without nested children.
Filter with relatedTarget — ignore child-boundary crossings when refactoring away from mouseover is not yet possible.
Highlight table rows — $("tr").on("mouseover", fn) on table rows with no nested interactive elements.
Show flat tooltips — reveal a tooltip when entering a trigger that has no nested content inside it.
Event delegation — $("#list").on("mouseover", "li", fn) when list items have no nested children.
Programmatic testing — $("#box").trigger("mouseover") to verify show logic in unit tests.
🧠 How mouseover Bubbling Differs from mouseenter
1
Pointer outside outer box
User has not entered the bound element — no over event yet.
outside
2
Pointer enters outer box
mouseover and mouseenter both fire — handler runs for a true entry from outside.
true enter
3
Pointer moves to child
mouseover fires on the parent and bubbles up. mouseenter stays silent — still inside the outer boundary.
child cross
4
👉
Stable hover
For nested menus and tooltips, use mouseenter + mouseleave — one enter, one leave, no duplicate firing from bubbling.
Important
📝 Notes
Bind with .on("mouseover", handler) since jQuery 1.7 — not the deprecated .mouseover(handler) method.
Trigger with .trigger("mouseover") since jQuery 1.0.
mouseoverbubbles — unlike mouseenter, it fires when moving from parent into a child.
Use event.relatedTarget to filter false positives when the pointer came from a child still inside the bound element.
For nested menus and tooltips, prefer mouseenter + mouseleave over mouseover + mouseout.
Any HTML element can receive mouseover — not limited to links or buttons.
Use .off("mouseover") to remove handlers — avoid deprecated .unbind("mouseover").
Touch devices have no true hover — provide click/tap fallbacks for critical UI.
Compatibility
Browser Support
The native mouseover event is supported in all browsers jQuery targets. jQuery’s .on("mouseover") (since 1.7) and .trigger("mouseover") (since 1.0) provide consistent collection binding, eventData, delegation, and programmatic triggering across browsers.
✓ jQuery 1.7+
jQuery mouseover event
Supported in jQuery 1.x, 2.x, and 3.x across all modern browsers. Native equivalent: element.addEventListener('mouseover', fn) — universal support; jQuery adds collection binding, eventData, delegation, and .trigger().
100%With jQuery loaded
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
mouseoverUniversal
Bottom line: Safe in any jQuery project. Prefer .on('mouseover') over deprecated .mouseover() for binding. For nested content, use mouseenter or filter with event.relatedTarget.
Wrap Up
Conclusion
The jQuery mouseover event fires when the pointer enters an element — and because it bubbles, it also fires when moving from a parent into a child inside the bound element. Bind handlers with .on("mouseover", fn), inspect event.relatedTarget to filter false positives, and fire handlers programmatically with .trigger("mouseover").
Choose mouseenter over mouseover when nested content would cause menus or tooltips to flicker from duplicate handler calls. Use the legacy mouseover + mouseout pair only on flat elements without nested children. Replace deprecated .mouseover(handler) with .on("mouseover", handler). For touch devices, remember hover has no mobile equivalent — add click fallbacks where needed.
Bind with .on("mouseover", handler) — the modern, delegation-capable API
Prefer mouseenter + mouseleave for nested menus and tooltips
Filter child crossings with event.relatedTarget when stuck on mouseover
Use CSS :hover when only colors or visibility change
Call .off("mouseover mouseout") when removing legacy hover behavior
❌ Don’t
Use deprecated .mouseover(handler) for new code — use .on("mouseover")
Bind mouseover on containers with nested submenus without filtering
Assume one mouseover equals one true entry — bubbling fires on child crossings too
Rely on hover alone for critical mobile UI — add tap/click fallbacks
Forget to unbind over/out handlers when tearing down SPAs
Summary
Key Takeaways
Knowledge Unlocked
Six things to remember about the mouseover event
Bubbles, filter, prefer enter.
6
Core concepts
.on01
.on("mouseover")
Bind
API
⚡02
.trigger()
Fire
Programmatic
bubble03
vs mouseenter
Bubbles
Compare
target04
relatedTarget
Filter
Pattern
out05
mouseout pair
Legacy
Hover
.off06
.off("mouseover")
Unbind
Cleanup
❓ Frequently Asked Questions
The mouseover event fires when the mouse pointer enters an element. In modern jQuery, bind handlers with .on('mouseover', handler) since version 1.7. Unlike mouseenter, mouseover bubbles — it re-fires when the pointer moves from a parent into a child inside the bound element. Any HTML element can receive mouseover.
When the pointer enters a child element, mouseover bubbles up to ancestor elements bound with .on('mouseover'). A handler on the outer menu container fires even though the user has not truly entered the menu from outside — moving into a submenu looks like a fresh entry on the parent. That duplicate firing flickers hover styles and re-opens dropdowns. For nested menus, prefer mouseenter and mouseleave instead.
event.relatedTarget is the DOM element the pointer came from when mouseover fired. If relatedTarget is still inside the bound element (for example, a sibling child div), you can ignore the event: if ($(event.relatedTarget).closest('#outer').length) return;. This filters false positives caused by bubbling across child boundaries without switching to mouseenter.
mouseover bubbles and fires when entering the bound element OR when moving from the parent into a child inside it. mouseenter fires only when the pointer enters the bound element from outside — child crossings are ignored. For hover menus, tooltips, and containers with nested content, mouseenter (paired with mouseleave) avoids menus flickering when the user moves into a submenu.
Call .trigger('mouseover') on the target element: $('#outer').trigger('mouseover'). Available since jQuery 1.0, trigger runs bound mouseover handlers. To run handlers without bubbling, use .triggerHandler('mouseover') instead.
The deprecated .mouseover(handler) method binds a mouseover handler directly on the collection — it is shorthand for .on('mouseover', handler) in older jQuery. For new code, use .on('mouseover', fn) instead of .mouseover(fn). The event name is the same; only the binding API changed when .on() became the standard in jQuery 1.7.
Did you know?
The jQuery API documentation explicitly warns that mouseover “can cause many headaches due to event bubbling” and points developers to mouseenter as a useful alternative. When the pointer enters the inner child of a nested box, mouseover fires on the inner element first, then bubbles to the outer — triggering show logic at inopportune times. jQuery added proprietary mouseenter and mouseleave events (originally IE-only) specifically to solve this problem.