Detect IF hovering over element with jQuery

JavascriptJquery

Javascript Problem Overview


I'm not looking for an action to call when hovering, but instead a way to tell if an element is being hovered over currently. For instance:

$('#elem').mouseIsOver(); // returns true or false

Is there a jQuery method that accomplishes this?

Javascript Solutions


Solution 1 - Javascript

Original (And Correct) Answer:

You can use is() and check for the selector :hover.

var isHovered = $('#elem').is(":hover"); // returns true or false

Example: http://jsfiddle.net/Meligy/2kyaJ/3/

(This only works when the selector matches ONE element max. See Edit 3 for more)

.

Edit 1 (June 29, 2013): (Applicable to jQuery 1.9.x only, as it works with 1.10+, see next Edit 2)

This answer was the best solution at the time the question was answered. This ':hover' selector was removed with the .hover() method removal in jQuery 1.9.x.

Interestingly a recent answer by "allicarn" shows it's possible to use :hover as CSS selector (vs. Sizzle) when you prefix it with a selector $($(this).selector + ":hover").length > 0, and it seems to work!

Also, hoverIntent plugin mentioned in a another answer looks very nice as well.

Edit 2 (September 21, 2013): .is(":hover") works

Based on another comment I have noticed that the original way I posted, .is(":hover"), actually still works in jQuery, so.

  1. It worked in jQuery 1.7.x.

  2. It stopped working in 1.9.1, when someone reported it to me, and we all thought it was related to jQuery removing the hover alias for event handling in that version.

  3. It worked again in jQuery 1.10.1 and 2.0.2 (maybe 2.0.x), which suggests that the failure in 1.9.x was a bug or so not an intentional behaviour as we thought in the previous point.

If you want to test this in a particular jQuery version, just open the JSFidlle example at the beginning of this answer, change to the desired jQuery version and click "Run". If the colour changes on hover, it works.

.

Edit 3 (March 9, 2014): It only works when the jQuery sequence contains a single element

As shown by @Wilmer in the comments, he has a fiddle which doesn't even work against jQuery versions I and others here tested it against. When I tried to find what's special about his case I noticed that he was trying to check multiple elements at a time. This was throwing Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover .

So, working with his fiddle, this does NOT work:

var isHovered = !!$('#up, #down').filter(":hover").length;

While this DOES work:

var isHovered = !!$('#up,#down').
                    filter(function() { return $(this).is(":hover"); }).length;

It also works with jQuery sequences that contain a single element, like if the original selector matched only one element, or if you called .first() on the results, etc.

This is also referenced at my JavaScript + Web Dev Tips & Resources Newsletter.

Solution 2 - Javascript

Use:

var hovered = $("#parent").find("#element:hover").length;

jQuery 1.9+

Solution 3 - Javascript

It does not work in jQuery 1.9. Made this plugin based on user2444818's answer.

jQuery.fn.mouseIsOver = function () {
    return $(this).parent().find($(this).selector + ":hover").length > 0;
}; 

http://jsfiddle.net/Wp2v4/1/

Solution 4 - Javascript

The accepted answer didn't work for me on JQuery 2.x .is(":hover") returns false on every call.

I ended up with a pretty simple solution that works:

function isHovered(selector) {

    return $(selector+":hover").length > 0

}

Solution 5 - Javascript

Set a flag on hover:

var over = false;
$('#elem').hover(function() {
  over = true;
},
function () {
  over = false;
});

Then just check your flag.

Solution 6 - Javascript

Couple updates to add after working on this subject for a while:

  1. all solutions with .is(":hover") break on jQuery 1.9.1
  2. The most likely reason to check if the mouse is still over an element is to attempt to prevent events firing over each other. For example, we were having issues with our mouseleave being triggered and completed before our mouseenter event even completed. Of course this was because of a quick mouse movement.

We used hoverIntent https://github.com/briancherne/jquery-hoverIntent to solve the issue for us. Essentially it triggers if the mouse movement is more deliberate. (one thing to note is that it will trigger on both mouse entering an element and leaving - if you only want to use one pass the constructor an empty function )

Solution 7 - Javascript

You can filter your elment from all hovered elements. Problematic code:

element.filter(':hover')

Save code:

jQuery(':hover').filter(element)

To return boolean:

jQuery(':hover').filter(element).length===0

Solution 8 - Javascript

Expanding on @Mohamed's answer. You could use a little encapsulation

Like this:

jQuery.fn.mouseIsOver = function () {
    if($(this[0]).is(":hover"))
    {
        return true;
    }
    return false;
}; 

Use it like:

$("#elem").mouseIsOver();//returns true or false

Forked the fiddle: http://jsfiddle.net/cgWdF/1/

Solution 9 - Javascript

I like the first response, but for me it's weird. When attempting to check just after page load for the mouse, I have to put in at least a 500 millisecond delay for it to work:

$(window).on('load', function() {
    setTimeout(function() {
        $('img:hover').fadeOut().fadeIn();
    }, 500);
});

http://codepen.io/molokoloco/pen/Grvkx/

Solution 10 - Javascript

Setting a flag per kinakuta's answer seems reasonable, you can put a listener on the body so you can check if any element is being hovered over at a particular instant.

However, how do you want to deal with child nodes? You should perhaps check if the element is an ancestor of the currently hovered element.

<script>

var isOver = (function() {
  var overElement;
  return {

    // Set the "over" element
    set: function(e) {
      overElement = e.target || e.srcElement;
    },

    // Return the current "over" element
    get: function() {
      return overElement;    
    },

    // Check if element is the current "over" element
    check: function(element) {
      return element == overElement;
    },

    // Check if element is, or an ancestor of, the 
    // current "over" element
    checkAll: function(element) {
      while (overElement.parentNode) {
         if (element == overElement) return true;
         overElement = overElement.parentNode;
      }
      return false;
    }
  };
}());


// Check every second if p0 is being hovered over
window.setInterval( function() {
  var el = document.getElementById('p0');
  document.getElementById('msg').innerHTML = isOver.checkAll(el);
}, 1000);


</script>

<body onmouseover="isOver.set(event);">
  <div>Here is a div
    <p id="p0">Here is a p in the div<span> here is a span in the p</span> foo bar </p>
  </div>
  <div id="msg"></div>
</body>

Solution 11 - Javascript

https://api.jquery.com/hover/

Asynchronous function in line 38:

$( ".class#id" ).hover(function() {
  Your javascript
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames SkidmoreView Question on Stackoverflow
Solution 1 - JavascriptMeligyView Answer on Stackoverflow
Solution 2 - Javascriptuser2444818View Answer on Stackoverflow
Solution 3 - JavascriptallicarnView Answer on Stackoverflow
Solution 4 - JavascriptgidimView Answer on Stackoverflow
Solution 5 - JavascriptkinakutaView Answer on Stackoverflow
Solution 6 - JavascriptDonald A Nummer JrView Answer on Stackoverflow
Solution 7 - JavascriptMinoView Answer on Stackoverflow
Solution 8 - JavascriptgideonView Answer on Stackoverflow
Solution 9 - JavascriptmolokolocoView Answer on Stackoverflow
Solution 10 - JavascriptRobGView Answer on Stackoverflow
Solution 11 - JavascriptLeonView Answer on Stackoverflow