connexo connexo - 3 months ago 9
CSS Question

:hover triggered directly after page reload on Firefox (but not on Mac OS X Chrome)

Please check this codepen with a) Firefox and b) Chrome. Proceed as follows:


  1. Move mouse on link

  2. Click link and do not move mouse cursor at all afterwards

  3. Wait until page has reloaded.



If you haven't moved the mouse cursor, it will still be above the link after the page has reloaded.

Firefox will apply the
:hover
styles now.

Chrome (Mac OS X) will display the element in it's non-hovered state (which is what I prefer in my scenario).

Anyone here who has an idea which browser does it right, and how to get one browser mimic the other's behaviour?

For my current scenario, I'd like to know how to avoid
:hover
being triggered directly after page reload
. I'd be quite unhappy if I had to resort to Javascript for that.

For completeness' sake, here's the demo's code:


<a href="https://codepen.io/connexo/pen/pEJbqj" target="_top">This Codepen</a>




a {
color: #333;
background-color: #ddd;
display: inline-block;
line-height: 40px;
padding: 20px;
text-decoration: none;
transition-duration: .4s;
&:before {
content: "non-hovered";
}
&:hover {
background-color: #a00;
color: white;
&:before {
content: "hovered state";
}
}
}


Edit: As one of my colleagues just told me, it seems that Chrome behaves in the described way only on OS X, but not on Windows. Can anybody elaborate on the whole issue?

Answer

Which behaviour is correct?

Difficult to say which is the correct behaviour as the W3C spec does not go into particular detail about the mechanics of the :hover pseudo class:

The :hover pseudo-class applies while the user designates an element with a pointing device, but does not necessarily activate it. For example, a visual user agent could apply this pseudo-class when the cursor (mouse pointer) hovers over a box generated by the element.

The user action pseudo-classes :hover, :active, and :focus

Both actions seem reasonable given the circumstances.

How to avoid :hover being triggered directly after page reload.

In this particular case it appears that you want to disable the hover state until the user has moved the mouse, to achieve this you could do the following:

  • Add the CSS property pointer-events: none; to the link on page load. This will disable any mouse events on the link
  • Attach a move event to the body which gets activated once when the user moves the mouse (after which it gets unbound)
  • In the move event set pointer-events: auto; on the link to enable mouse events on it

$("a").css("pointer-events", "none");
$("body").one("mousemove", function() {
  $("a").css("pointer-events", "auto");
});
a {
  color: #333;
  background-color: #ddd;
  display: inline-block;
  line-height: 40px;
  padding: 20px;
  text-decoration: none;
  transition-duration: .4s;
}
a:before {
  content: "non-hovered";
}
a:hover {
  background-color: #a00;
  color: white;
}
a:hover:before {
  content: "hovered state";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" target="_top"></a>

The example is best viewed in either Codepen or JS Fiddle given that a Stack Snippet is collapsed by default.