142

Is there a pseudo-class in CSS to specify

:not(:hover)

Or is that the only way to specify an item that is not being hovered?

I went through several CSS3 references, and I see no mention of a CSS pseudo-class to specify the opposite of :hover.

4
  • 1
    Instead element:not(:hover) use element. Commented Jun 14, 2015 at 22:24
  • 7
    @lmgonzalves That will not work; that will force the style in both hovered and non-hovered states. Commented Jun 14, 2015 at 22:26
  • Why not :not(:hover)?
    – Oriol
    Commented Jun 14, 2015 at 22:53
  • @Oriol Only because it is not as clean as a non-negated pseudo-class and because it might be computationally more expensive than a pseudo-class designed for that purpose. Commented Jun 14, 2015 at 23:00

4 Answers 4

246

Yes, use :not(:hover)

.child:not(:hover){
  opacity: 0.3;
}

.child {
  display: inline-block;
  background: #000;
  border: 1px solid #fff;
  width: 50px;
  height: 50px;
  transition: 0.4s;
}

.child:not(:hover) {
  opacity: 0.3;
}
<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Another example; I think you want to: "when one is hovered, dim all other elements".

If my assumption is correct, and assuming all your selectors are inside the same parent:

.parent:hover .child{
  opacity: 0.2;      // Dim all other elements
}
.child:hover{
  opacity: 1;        // Not the hovered one
}

.child {
  display: inline-block;
  background: #000;
  border: 1px solid #fff;
  width: 50px;
  height: 50px;
  transition: 0.4s;
}

.parent:hover .child {
  opacity: 0.3;
}

.parent .child:hover {
  opacity: 1;
}
<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Otherwise... simply use the default logic:

.child{
  opacity: 0.2;
}
.child:hover{
  opacity: 1;
}
4
  • 1
    Your first sentence (assuming it is correct!) sounds like the answer. Thanks! I couldn't find an appropriate CSS pseudo-class, because it must not exist (yet). The examples you provided are not applicable to what I'm working on, but are very useful and helpful, regardless. I wonder how expensive that first example would be, as it matches almost everything. Any thoughts? Commented Jun 14, 2015 at 22:47
  • @RockPaperLizard well, if you use 1000 child elements im might get a bit slow jsbin.com/hazega/1/edit?html,css,output otherwise, 100, 200 elements should work really fine. Commented Jun 14, 2015 at 22:50
  • 2
    Thanks. Works for:not(:disabled) too and I assume a ton other similar attributes. Commented May 20, 2019 at 15:04
  • In second snippet, you could just write .parent:hover .child:not(:hover) { opacity: 0.3; }
    – NNL993
    Commented Jun 9, 2023 at 20:49
5

There isn't such a pseudo-class. There doesn't need to be, when you can just use :not(:hover). The whole point of the :not() pseudo-class is to allow authors to write negations without having to specify separate negations of every existing (and future) dynamic pseudo-class where an element can only either match or not match the pseudo-class.

For example, only some elements can either be :enabled or :disabled — most elements are neither because the semantics simply don't apply — but an element can only either be designated by the pointing device (:hover), or not (:not(:hover)). Providing negations that can already directly be achieved using :not() would greatly undermine its usefulness (though it could still be used to negate any other simple selector — or entire complex selectors down the road).

The argument that such a pseudo-class would be computationally less expensive is pretty weak. The most naïve implementation of such a pseudo-class would be a literal :not(:hover) check, which would be no better. Any more complex or optimized implementations and you're asking vendors to implement a pseudo-class that is either as fast as or even faster than :not(:hover), something that's already uncommon enough of a use case considering the other options you have such as cascading and :not(:hover) (for whenever cascading isn't an option) that you readily have access to. It simply doesn't justify the time and effort to spec, implement and test an alternative to at least one other existing method that is 100% functionally equivalent (and one that applies to at least 80% of scenarios). And there's also the issue of naming such a pseudo-class — you haven't proposed a name for it, and I can't think of a good one either. :not-hover is only shorter by two bytes and only marginally less work to type. If anything, it's potentially more confusing than :not(:hover).

If you are worried about specificity, note that the :not() pseudo-class itself is not counted for specificity; only its most specific argument is. :not(:hover) and :hover are equally specific. So specificity is not an issue either.

If you are worried about browser support, such a pseudo-class, if introduced, would likely have either been introduced alongside :not(), or in a later level of Selectors, since it didn't appear in CSS2 (where :hover was first introduced more than 17 years ago, and first implemented in IE4 another year yet before). Introducing it in a later level would be pointless because authors would simply be forced to continue using :not(:hover) until browsers begin implementing this new pseudo-class anyway, and they would have no reason to switch.

Note that this isn't the same as the following question, which talks about events vs states (it's originally about :focus rather than :hover, but the same principle applies): Does CSS have a :blur selector (pseudo-class)?

4

If you want to display something only on hovering on something else, u can use

selector:not(:hover)

like this:

section{
   font-size:3em;
}

div:not(:hover) + section{
 display:none;
}
<div>Hover on me</div>

<section>Peek A Boo!</section>

There are several unusual effects and outcomes when using :not() that you should keep in mind:

  • :not(:not(...)), :not(p::before) is not possible
  • :not(*) would obviously never be applied
  • :not(.foo) will match anything that isn't .foo, including tags such as <HTML> and <body>
  • increases the specificity of a rule, for ex: #foo:not(#bar) will match the same element as the simpler #foo, but has a higher specificity.

and operation with :not :

  • Elements that are not <div> and not <span> elements: body :not(div):not(span){}

or operation with :not, this isn't well supported yet.

  • Elements that are not .crazy or .fancy : body :not(.crazy, .fancy){}

Source MDN

0
a {
  /*styles*/
} 

is a normal (non hovered link)

a:hover {
  /*styles*/
} 

is a hovered link

3
  • 2
    This is not accurate. The first will style the item, both when hovered and not hovered, unless the second is also specified. Regardless, the first is applied in both states, and the second will just override it in one of the two states. Commented Jun 14, 2015 at 22:34
  • You are right about that. But that is thow it is done and also the only way to do it with css. What is it actually that you want to achieve?
    – nikola_wd
    Commented Jun 14, 2015 at 22:36
  • Thanks. I added a comment that answers your question in the main question section above because another SO user asked the same question as yours. Commented Jun 14, 2015 at 22:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.