Question

Sometimes it appears helpful to make certain page elements only visible on e.g. hovers. An example is stackoverflow's "feedback - Was this post useful to you?"-widget. As those elements might be crucial to the interface, such a show-on-hover-feature should be a progressive enhancement or, in other terms, unobtrusive and degrade gracefully.

The usual way appears to be employing javascript, e.g. hiding the elements and making them available when a parent element is hovered. The reason for that choice might be :hover is not support for all elements especially in legacy browsers, thereby forbidding you to hide elements in the first place up to css2. (for a js/jQuery example cf. jquery showing elements on hover)

I wonder if you can achieve such a feature safely* with pure css3, using :not(:hover) and :hover, not affecting older browsers. As far as I can see, the requirement is that every browser supporting :not() must support :hover for all elements. According to the following sources, that appears to be the case

Example implementation: http://jsfiddle.net/LGQMJ/

What do you think? Any objections or other sources?

*by safely I mean the browser should always show all elements as a last resort.

Was it helpful?

Solution

Your solution looks alright for CSS3. There isn't anything I can think of to improve your solution for modern browsers as the opacity property will never be applied by browsers that don't support it anyway.

There is literally no other browser besides IE6 and NN4 (and older) without support for :hover on elements other than a. As implied in your question, all browsers that support :not() are known to also fully support :hover.

That said, you end up leaving IE7 and IE8 missing out on the hover effect, the latter of which is still quite prevalent. You're probably looking to support IE6 as well, but here's a solution that I believe will address these concerns, if you need it:

  1. Omit :not(:hover) altogether so your first selector becomes less specific rather than equally specific to your second selector with :hover, and you can reach out to IE7 and IE8 which don't support :not() but do support :hover on all visual elements:

    div span.question {
        opacity: 0;
    }
    div:hover span.question {
        opacity: 1;
    }
    
  2. Use the visibility property instead of the opacity property to reach out to IE7 and IE8 which don't support CSS3 opacity:

    div span.question {
        visibility: hidden;
    }
    div:hover span.question {
        visibility: visible;
    }
    

    Keep in mind that visibility: hidden will make an element invisible to mouseovers as well, but in this case you're applying it to a child element, so the parent will remain visible to mouseovers.

  3. Use CSS2/3 combinators that IE6 doesn't support but IE7 and IE8 do (child >, adjacent sibling +, general sibling ~) to hide both rules from IE6. This borders on "hacky", but your situation is one where the child combinator > fits very well, so it can be integrated organically rather than hacked in like the famous html > body filter:

    div > span.question {
        visibility: hidden;
    }
    div:hover > span.question {
        visibility: visible;
    }
    

Updated fiddle

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top