Grow your CSS skills. Land your dream job.

Hover on “Everything But”

Published by Chris Coyier

Adding a hover state to an element is durn easy. Let's use an opacity change as an example:

div {
   opacity: 1.0;
}
div:hover {
   opacity: 0.5;
}

But what if we want to have that hover state apply to everything but the element actually being hovered over? (e.g. other adjacent sibling divs)

Let's assume this basic HTML:

<section class="parent">
  <div></div>
  <div></div>
  <div></div>
</section>

We'll apply the current CSS properties to all the children of the parent when the parent is in the hover state.

.parent:hover > div {
  opacity: 0.5;
}

Then when the parent is hovered and the individual div is hovered, we bump the opacity back up, giving the final effect we are looking for.

.parent:hover > div:hover {
  opacity: 1.0;
}

Real World?

A similar kind of thing is in the Twitter for Mac app on individual tweets:

Demo

This idea can be extended into multiple levels of depth. Here is an example of three "lists." All list items have full opacity in their regular state, but as you roll over the lists, the currently hovered list is slightly more opaque than then others, and the currently hovered list item is fully opaque.

View Demo   Download Files

And yes, old you-know-who browsers don't do :hover on anything but anchor links. If it's mission critical, use JavaScript to detect mouseenter events on them and apply/remove class names.

Update August 2012: Michelle Eaton writes in with this JavaScript to do the job, if you must:

$("#all ul li").hover(function() { // Mouse over
  $(this).siblings().stop().fadeTo(300, 0.6);
  $(this).parent().siblings().stop().fadeTo(300, 0.3); 
}, function() { // Mouse out
  $(this).siblings().stop().fadeTo(300, 1);
  $(this).parent().siblings().stop().fadeTo(300, 1);
});

Comments

  1. Permalink to comment#

    Love this, thanks.

  2. Enrique Moreno Tent
    Permalink to comment#

    Chris, do you know that your website doesnt render well? At leas in my conditions (Chromium under Ubuntu Linux). I don’t know if this is also true of other OS. Please check it out, because it has gone on for long time and it’s driving me crazy.

  3. Permalink to comment#

    this is kind of obvious.. but i love that you’ve done on the demo page :-)

  4. felipe
    Permalink to comment#

    Awesome demo!
    And am I the only one having problems seeing things (menu text and text in other areas) on css-tricks?

  5. Permalink to comment#

    I do this on my site. Similar syntax

    <style>
       ul:hover li{ color: gray; }
       ul:hover li:hover{ color: navy; }
    <style>
    <ul>
       <li>item</li>
       <li>item</li>
       <li>item</li>
    </ul>

    it’s a neat effect. doesn’t work in older versions of IE, but I can live with that

  6. Eric
    Permalink to comment#

    Google Page Speed declares that this is a “potentially inefficient use of :hover” which has been known to cause issues with other hovering effects on some pages. most notably IE versions, but ive seen this bleed through and cause performance issues with hovering in FF as well.

    Be warned.

  7. Kim
    Permalink to comment#

    I appreciate that you provide the code and a demo. Thanks!

  8. This is nice post. It’s really useful. Thanks for shearing your ideas!

  9. very cool, I am doing that plus a little more css transitions on the nav on my current site. I will say that using css to handle things that you would normally use an image for will help your load time greatly.

  10. sc
    Permalink to comment#

    but, is there some reason to put the “:hover” on every selectors? I mean, is not enough to put it just in the las one you are interested on being hovered?

    • bezoeker
      Permalink to comment#

      It actually is, I did a quick test with Web Developer toolbar and reduced that part to:

      #all:hover a {
      opacity: 0.2;
      }
      #all ul:hover a {
      opacity: 0.5;
      }
      #all ul a:hover {
      opacity: 1;
      }

      Only tried it in Firefox though, maybe it’s a fix for other browsers

    • Permalink to comment#

      it’s because, in this example, we want a group of items we’re not hovering on to change, while the one we’re actually hovering on stays the same.

      To do this, we need to change all of the items in the group (i.e., #.parent:hover ), and then change the one item we’re actually hovering on ( .parent:hover > .item:hover ) back to its original value.

    • Permalink to comment#

      nevermind; I see what you mean.

      It does appear to work in modern browsers (I tried in Fx3.6, Opera11, and Chrome10).

      When I was implementing this on my own site (it was a couple years ago), I remember I was forced to use the extra :hover selectors – I don’t remember which browsers required them, however.

  11. Permalink to comment#

    Genius! I’ll definitely be implementing this in my site. Thanks!

  12. Permalink to comment#

    very neat post!

  13. Permalink to comment#

    Nice post! I can always learn something from you, thanks!

  14. Permalink to comment#

    Nice!! I’m going to use this straight away!!

  15. Permalink to comment#

    You might have some mystic force – I just looked for that, thanks Chris!

  16. Thanks a lot! This is clean and easy!!

    This is a wonderful idea!!

  17. Awesome demo! Simple tricks. I give it a try..

  18. Permalink to comment#

    usefull tutorial for me, thanks

  19. The Demo is cool, love it. Can’t wait to see how this hovering thing work. Thanks

  20. Debbie
    Permalink to comment#

    Thanks for another addition to my CSS arsenal.

  21. Older Version of Browsern do not understand the :hover for div, li, etc. For this Browsers you can write a little bit of javascript to show the hover effect.

    • I too agree with your point. This is cool. but seeing current implementations by the browsers, I would still prefer java script based approach to achieve similar effect.

      http://www.technobits.net – Latest buzz, tips and tricks in Software Development.

  22. Perhaps someone can help. My site is like a shopping mall map (like going to a physical mall and looking at the directory) and I would like to change the opacity of a group of stores (class) based on hovering on the legend entry of the same class. Because you can search and filter the stores in various ways, the structure and order of the stores is fluid but I use class to color code the background images.

    The basic structure is below. I can have the legend as another div inside the mall if that helps but the question is:

    Can I hover over class ‘shoes’ in the legend and highlight ‘store_1′ and ‘store_4′ (and any other shoe stores) based on their class?

    (BTW, if you can do that I highly recommend writing up a separate blog entry – I’m sure lots of people would be interested.)


    <div id="mall_stores">
    <div id="store_1" class="shoes">...</div>
    <div id="store_2" class="electronics">...</div>
    <div id="store_3" class="books">...</div>
    <div id="store_4" class="shoes">...</div>
    ...
    </div>
    <div id="legend">
    <div id="class_1" class="shoes">shoes</div>
    <div id="class_2" class="electronics">electronics</div>
    <div id="class_3" class="books">books</div>
    </div>

  23. Robert
    Permalink to comment#

    Hi;
    OK, I’m still way back at the starting line for CSS so I’ve still got lots of questions.
    One of which is what is the “>” used for in the code like here (from above)
    .parent:hover > div { opacity: 0.5;} ?

    • The “>” is the child selector. So in the example you use it will select only those div tags that are children of something with the class “parent” that is being hovered on.

      It differs from the usual “ancestor descendant” selector in that it only selects direct children, not descendants further down the tree.

      So a selector like “div a” will select all tags within a but “div > a” will not select an that is within a within a .

    • Ah, HTML is interpreted. So my last paragraph should be:

      So a selector like “div a” will select all <a> tags within a <div&tg; but “div > a” will not select an <a> that is within a <p> within a <div>.

  24. Permalink to comment#

    I love this! This is the kind of tut that makes me want to go back and redesign about 1000 things.

  25. Aman
    Permalink to comment#

    Wow this looks really cool, I see lot of potential for this. But this doesn’t seem to work with Internet Explorer!

  26. Ron
    Permalink to comment#

    hey Chris,

    as $(‘every #day > .hour: first’).educateMe(‘http://feeds2.feedburner.com/CssTricks’)

    Let me not use words like amazing, love or aaaaaawsaaaam* :hover{ so much energy, so much enthusiasm, so unbelievable MUCH time for needed real social work (->sharing) – that it is (if I think back, when I started learning, trying  constantly landed on your site after goo’ling smth…) ! }

    This technique is found in almost all my sheets. Would love to see more of this kind of tricks -> published at this “prominent/celebrated” site – that it is! BECAUSE FireFoxyBaby – that it WAS – does not please anymore. So if you got anymore of those “simple” tricks for which I use usually
    if(!$.browser.mozilla) JS
    else THANKS!

    .a.hover strong: { border:1px solid black; }
    .a:hover strong.no_border { border:0; }
    .a:hover > strong:first-child:hover { border:1px solid blue; }
    c:hover .a:hover > strong:first-child:hover { border:1px solid red; }

    You are a sweet one! That’s why people come back: You didn’t make a tut out of it. :)

    Would love to work one day with you… “own” site is down right now (but you see the email.address ) – could be nice, would be really nice.

    Usually don’t do comments – first timer, almost(that it is) -> was tired of empty phrases.

    *smash_mag

  27. Ron
    Permalink to comment#

    * hover-on-everything-if

  28. Nice and useful article. Thanks

  29. Permalink to comment#

    nice tutorial, but have you tested your site in chrome?

  30. Permalink to comment#

    Take a look at the css3-pseudo class “:not()”

    http://www.w3.org/TR/css3-selectors/#negation

  31. Good Job.
    :hover pseudo has issues with older versions of IE.
    IE sucks!

  32. Excellent. Really focuses the user on the target area – will certainly be using that in my next website project. Thanks.

  33. Nope! IE is a big effect on these kind of approaches.

  34. manoj
    Permalink to comment#

    i can use it on image gallery… coool… :)

  35. josephhyunkim
    Permalink to comment#

    great post

  36. Tim
    Permalink to comment#

    You can do this faster with :not

    div:not(:hover){opacity:0.5}

    Or using your demo:

    #all:hover a:not(:hover) {
    opacity: 0.5;
    }

    Instead of:

    #all:hover ul:hover a {
    opacity: 0.5;
    }
    #all:hover ul:hover a:hover {
    opacity: 1;
    }

  37. Petter
    Permalink to comment#

    This helped me alot, thanks alot mate :)

  38. Prashanth
    Permalink to comment#

    Great article. If images we can greyscale the other images.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".