2

When hovering over an element and then refreshing the page (without moving the mouse):

  • Chrome does not fire the mouseenter event on page load
  • Firefox does fire the mouseenter event on page load

Below is an example snippet. To reproduce the issue, hover over the div and then refresh the page. In Chrome, the div does not contain "mouseenter". In Firefox, it does.

Note that this does not work in the Stacksnippets environment since you need to click "run snippet" first. JSFiddle: https://jsfiddle.net/9fu6cx5d/7/

let div = document.getElementById('my-div');

div.addEventListener('mouseenter', function () {
  div.innerHTML = 'mouseenter';
});
#my-div {
  width: 150px;
  height: 150px;
  background-color: #aaaaaa;
}
<div id="my-div">
</div>

Which browser has the correct behaviour? How can I work around the difference in behaviour or at least make them both behave the same?

Chrome version: 59.0.3071.115 (Official Build) (64-bit)

Firefox version: 54.0 (64-bit)

Pieter van den Ham
  • 4,381
  • 3
  • 26
  • 41
  • 1
    The behavior can be demonstrated here if you focus the "run" button, move the mouse to the below area, and activate with the enter key. – Josh Lee Jul 11 '17 at 12:27
  • 1
    `The mouseenter event is fired when a pointing device (usually a mouse) is moved over the element that has the listener attached.` According to the docs, Chrome is the one with the correct behaviour. As for a work around maybe try it inside a on document ready? – Deckerz Jul 11 '17 at 12:27
  • I'm having this problem in a React component. mouseenter causes re-render, which causes mouseenter event, and so on looping and crashing app. Have there been any updates? How can I prevent mouseenter events triggered by page reload? – NicoWheat Jun 21 '20 at 01:57

2 Answers2

1

As pointed out in the comments, Chrome's behavior is the correct one according to the specs. Below is an idea on how to work around the difference.

You can make sure you get the value right by checking whether the mouse is inside the bounds of the div on document load. Unfortunately there is no way in JS to check the mouse position without firing events, so you will have to resort to some hack involving CSS hover rules and checking against them on $(document).ready.

To quote this hilarious answer:

Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 elements (so that the :hover pseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hover rule for those elements that changes a property (let's say font-family). In your load handler, cycle through each of the 4 million elements, checking currentStyle / getComputedStyle() until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.

N.B. DON'T DO THIS.

While you definitely shouldn't do this, the general idea of using non-effective hover styles for the sake of checking if an element is hovered without needing JS events is a good one if you just need to work around browser quirks. I'm using font-weight in the example below, but you can change it to whatever works for you.

The css

#my-div:hover {font-weight:700;}

The js

// Pseudocode!

var mouseIsInside = false,
    div = $('#my-div');

$(document).ready(function(){
    if (div.css('font-weight') === 700) {
        mouseIsInside = true;
    }

    doStuffIfMouseInside();
});

div.on('mouseenter', function(){
    mouseIsInside = true;
    doStuffIfMouseInside();
})

function doStuffIfMouseInside() {
    if (mouseIsInside) {
        ...
    }
}
ppajer
  • 3,045
  • 1
  • 15
  • 22
  • Chrome behavior is certainly not the correct one, they're not even consistent with themselves, see [this fiddle](https://jsfiddle.net/vhnjp0e8/) where a new node is appended and on which the mouseenter event will fire, if the mouse was active on the document first. Even the : hover hack wouldn't work because they just are lazy to check the mouse state at page load and won't mark :hovered elements at all before the mouse is active. – Kaiido Jan 06 '21 at 08:49
0

If you add (function(){})(); around your code it seems to work in both browsers.

It seems that firefox might be firing events before the dom is available causing problems with mousein/out events.

See: https://jsfiddle.net/9fu6cx5d/8/

Deckerz
  • 2,606
  • 14
  • 33