pure javascript to check if something has hover (without setting on mouseover/out)

JavascriptJqueryHover

Javascript Problem Overview


I have seen this jQuery syntax:

if($(element).is(':hover')) { do something}

Since I am not using jQuery, I am looking for the best way to do this in pure javascript.

I know I could keep a global variable and set/unset it using mouseover and mouseout, but I'm wondering if there is some way to inspect the element's native properties via the DOM instead? Maybe something like this:

if(element.style.className.hovered === true) {do something}

Also, it must be cross browser compatible.

Javascript Solutions


Solution 1 - Javascript

Simply using element.matches(':hover') seems to work well for me, you can use a comprehensive polyfill for older browsers too: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches

Solution 2 - Javascript

You can use querySelector for IE>=8:

const isHover = e => e.parentElement.querySelector(':hover') === e;    

const myDiv = document.getElementById('mydiv');
document.addEventListener('mousemove', function checkHover() {
  const hovered = isHover(myDiv);
  if (hovered !== checkHover.hovered) {
    console.log(hovered ? 'hovered' : 'not hovered');
    checkHover.hovered = hovered;
  }
});

.whyToCheckMe {position: absolute;left: 100px;top: 50px;}

<div id="mydiv">HoverMe
  <div class="whyToCheckMe">Do I need to be checked too?</div>
</div>

to fallback I think it is ok @Kolink answer.

Solution 3 - Javascript

First you need to keep track of which elements are being hovered on. Here's one way of doing it:

(function() {
    var matchfunc = null, prefixes = ["","ms","moz","webkit","o"], i, m;
    for(i=0; i<prefixes.length; i++) {
        m = prefixes[i]+(prefixes[i] ? "Matches" : "matches");
        if( document.documentElement[m]) {matchfunc = m; break;}
        m += "Selector";
        if( document.documentElement[m]) {matchfunc = m; break;}
    }
    if( matchfunc) window.isHover = function(elem) {return elem[matchfunc](":hover");};
    else {
        window.onmouseover = function(e) {
            e = e || window.event;
            var t = e.srcElement || e.target;
            while(t) {
                t.hovering = true;
                t = t.parentNode;
            }
        };
        window.onmouseout = function(e) {
            e = e || window.event;
            var t = e.srcElement || e.target;
            while(t) {
                t.hovering = false;
                t = t.parentNode;
            }
        };
        window.isHover = function(elem) {return elem.hovering;};
   }
})();

Solution 4 - Javascript

it occurred to me that one way to check if an element is being hovered over is to set an unused property in css :hover and then check if that property exists in javascript. its not a proper solution to the problem since it is not making use of a dom-native hover property, but it is the closest and most minimal solution i can think of.

<html>
    <head>
        <style type="text/css">
#hover_el
{   
    border: 0px solid blue;
    height: 100px;
    width: 100px;
    background-color: blue;
}   
#hover_el:hover
{   
    border: 0px dashed blue;
}
        </style>
        <script type='text/javascript'>
window.onload = function() {check_for_hover()};
function check_for_hover() {
    var hover_element = document.getElementById('hover_el');
    var hover_status = (getStyle(hover_element, 'border-style') === 'dashed') ? true : false;
    document.getElementById('display').innerHTML = 'you are' + (hover_status ? '' : ' not') + ' hovering';
    setTimeout(check_for_hover, 1000);
};
function getStyle(oElm, strCssRule) {
    var strValue = "";
    if(document.defaultView && document.defaultView.getComputedStyle) {
        strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
    }
    else if(oElm.currentStyle) {
        strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1) {
            return p1.toUpperCase();
        });
        strValue = oElm.currentStyle[strCssRule];
    }
    return strValue;
};
        </script>
    </head>
    <body>
        <div id='hover_el'>hover here</div>
        <div id='display'></div>
    </body>
</html>

(function getStyle thanks to https://stackoverflow.com/questions/4172871/javascript-get-styles)

if anyone can think of a better css property to use as a flag than solid/dashed please let me know. preferably the property would be one which is rarely used and cannot be inherited.

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
QuestionmulllhausenView Question on Stackoverflow
Solution 1 - JavascriptHughethView Answer on Stackoverflow
Solution 2 - Javascriptzb'View Answer on Stackoverflow
Solution 3 - JavascriptNiet the Dark AbsolView Answer on Stackoverflow
Solution 4 - JavascriptmulllhausenView Answer on Stackoverflow