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?

Brian Phillips
  • 4,302
  • 2
  • 25
  • 40
Yuriy Galanter
  • 38,833
  • 15
  • 69
  • 136
  • 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? – Amber Jan 02 '14 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. – Yuriy Galanter Jan 02 '14 at 16:22
  • http://www.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. – Hecksa Jan 02 '14 at 16:27
  • have you tried implementing the above using jQuery? – Shourya Sharma Jan 02 '14 at 18:28
  • Hmm... I tried using `visibility` instead, but that didn't work either. :( – hkk Jan 02 '14 at 18:30
  • @cloudcoder2000 jQuery helped you make the above code cross-browser complaint :D – Shourya Sharma Jan 02 '14 at 18:46
  • I think this could be a browser related issue. I found this as a bug on webkit: https://bugs.webkit.org/show_bug.cgi?id=4117 and also this could be related: https://bugs.webkit.org/show_bug.cgi?id=120786 – Giulio Bonanome Jan 02 '14 at 19:55
  • @GiulioBonanome it does look similar, tho not sure if anybody reported CSS issues (not JS events) – Yuriy Galanter Jan 02 '14 at 20:08
  • @YuriyGalanter 4117 issue mention :hover in the object and inside 120786 comments is said that "mouseenter/-leave is handled by the same code as CSS hover". I hope to raise attention to the CSS problem there :) – Giulio Bonanome Jan 02 '14 at 22:16

3 Answers3

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

hkk
  • 2,069
  • 1
  • 23
  • 48
  • 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. – Yuriy Galanter Jan 02 '14 at 20:04
  • @YuriyGalanter Unless someone makes a hack to do this, I think Javascript may be your only option. – hkk Jan 03 '14 at 19:13
  • 1
    @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. – Yuriy Galanter Jan 03 '14 at 19:59
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

RyanY
  • 635
  • 1
  • 8
  • 20
  • Wouldn't the element still take up space in the viewport this way, though? – Hecksa Jan 02 '14 at 16:31
  • When `display: none;` is applied to an element it doesn't take any physical space, but it's still part of the DOM. – myajouri Jan 02 '14 at 16:35
  • 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 Jan 02 '14 at 16:36
  • 1
    @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. – Yuriy Galanter Jan 02 '14 at 16:43
  • @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. – Hecksa Jan 02 '14 at 16:43
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.

Community
  • 1
  • 1
Brian Phillips
  • 4,302
  • 2
  • 25
  • 40
  • 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. – Yuriy Galanter Jan 02 '14 at 20:01
  • @YuriyGalanter You could try setting the position to absolute to prevent it from taking up flow on the page. See my update – Brian Phillips Jan 02 '14 at 20:19