12

I created a very basic sample:

HTML

<div id="bla"></div>

CSS

#bla {
    width:400px;
    height:400px;
    background-color:green;
    display:none;
}

#bla:hover{
   background-color:red;
}

As you can see it's a DIV that is initially hidden and changes color when mouse hovers over it.

This JavaScript unhides it after 2 seconds

setTimeout(function() {
     document.getElementById('bla').style.display="block";
},2000)

But if you place your mouse over location where the DIV is about to appear - when it appears - it appears in unhovered state. Only when you actually move the mouse - hover effect takes place.

Here's a demo. Run it and immediately place mouse over result pane.

Is this by design? Is there a way (without JS preferable) to detect that DIV is hovered?

9
  • 1
    What browser are you using, for me it works fine (red when hovering, even if mouse is still on where it appears before it appears; green when not hovering) on FF, perhaps it is compatibility? Commented Jan 2, 2014 at 16:18
  • @Amber thanks for the pointer - in FF it does behave correctly. I am seeing the issue in Webkit browsers (Chrome, Opera, Safari) as well as IE. Interesting. Commented Jan 2, 2014 at 16:22
  • w3.org/TR/css3-selectors/#useraction-pseudos - the spec isn't really very particular about implementation of :hover, so I guess this is just a blind spot. I don't think it's unreasonable to call it a bug, though. Commented Jan 2, 2014 at 16:27
  • have you tried implementing the above using jQuery? Commented Jan 2, 2014 at 18:28
  • Hmm... I tried using visibility instead, but that didn't work either. :( Commented Jan 2, 2014 at 18:30

3 Answers 3

1

While you can use opacity, @BrianPhillips mentioned, it doesn't work in IE 8. I don't know of a pure CSS solution, but here's a concise enough Javascript workaround:

window.onmousemove=function(event){
    ev = event || window.event;
    if (event.pageX <= 400 && event.pageY <= 400){
        document.getElementById('bla').style.backgroundColor= "red";
    } else {
        document.getElementById('bla').style.backgroundColor= "green";
    }
}
setTimeout(function() {
     document.getElementById('bla').style.display="block";
},2000)

Demo

Sign up to request clarification or add additional context in comments.

3 Comments

While I prefer not to use JavaScript for pure CSS functionality it looks like this is the only viable solution. I will still look for a while longer but if I don't find a pure CSS solution this is a prime answer candidate.
@YuriyGalanter Unless someone makes a hack to do this, I think Javascript may be your only option.
@BrianPhillips did offer a CSS solution (absolute positioning) but I still like this solution better despite extra JS used. Hopefully this will be recognized as a bug and fixed in future releases.
0

When you set display to none the image takes up no space meaining there is nowhere to hover over.

I would set the background-image in you css to rgba(0 0 0 0); making it invisible but still in the dom. You can then change your javascript to

setTimeout(function() {
     document.getElementById('bla').style.backgroundColor="green";
},2000);

http://jsfiddle.net/euT7k/3

5 Comments

Wouldn't the element still take up space in the viewport this way, though?
When display: none; is applied to an element it doesn't take any physical space, but it's still part of the DOM.
Yes, but it has to take up space in the viewport in order for hover to work, otherwise there is no object to hover over until the object has space in the view port. @myajouri, thank for the catch, I edited the answer above.
@RyanY the idea is object not being initially there, but when it does appear - it appears right under mouse - already hovered. With your approach it is always there so when I move my mouse there before 2sec timeout - hover takes effect right away. Setting "display" is just a simulation - in reality it could be page reload, dynamic DOM element added etc. Also, I'd prefer not to change inline style and play with "!important" attributes.
@RyanY - Given that the example works in Firefox, I don't think it's required for the element to take up space for hover to work. Your answer is definitely useful for certain situations, but I feel like requiring the space on the screen to be "empty" is going to cause problems in most cases.
0

You could try using CSS opacity along with setting it to position: absolute to prevent it from taking up flow on the page. This appears to work properly:

CSS:

#bla {
    width:400px;
    height:400px;
    background-color:green;
    opacity: 0;
    position: absolute;
}

JS:

setTimeout(function() {
         document.getElementById('bla').style.opacity="1";
         document.getElementById('bla').style.position="relative";
},2000)

Demo

The key here is that elements with opacity respond to events (click, hover, etc), while elements with visibility: hidden and display:none do not. (source)

Note that opacity isn't available in IE 8 and below.

2 Comments

This is somewhat similar to @RyanY answer (though a neater implementation). The element is still there intially and taking space even though it is transparent.
@YuriyGalanter You could try setting the position to absolute to prevent it from taking up flow on the page. See my update

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.