htmlcsscss-selectorspseudo-class

Why does the hover pseudo-class override the active pseudo-class?


I have an element which I want to change color on :hover, but while clicked, I want it to switch back to its original color. I've tried this:

a:link, a:visited, a:active {
    background: red;
}
a:hover {
    background: green;
}

As it turns out, this doesn't work. I realized that the :hover state was overriding the :active state. This was easily solved by this:

a:link, a:visited {
    background: green;
}
a:hover {
    background: red;
}
a:active {
    background: green;
}

(I could combine the 1st rule with the 3rd one).

Is this the expected behavior? As far as I understand this, the :active state should always override the :hover state, since the :active state will almost always be accompanied with the :hover state.

a.noworks:link,
a.noworks:visited,
a.noworks:active {
  background: red;
}

a.noworks:hover {
  background: green;
}


a.works:link,
a.works:visited {
  background: green;
}

a.works:hover {
  background: red;
}

a.works:active {
  background: green;
}

a {
  display: block;
  width: 100px;
  height: 100px;
  color: #fff;
  text-decoration: none;
  text-align: center;
  font-weight: bold;
  font-size: 30px;
  float: left;
  margin-left: 20px;
}

span {
  font-size: 16px;
  display: block;
  margin: 0 auto;
}
<a href="#" class="noworks">
    Click me!! <span>(broken)</span>
</a>
<a href="#" class="works">
    Click me!! <span>(works)</span>
</a>


Solution

  • Yes, this is expected behavior.

    Let's take a look at another example. Just adding two classes:

    <ul>
    <li class="item first">item</li>
    <li class="item">item</li>
    <li class="item">item</li>
    <li class="item">item</li>
    <li class="item last">item</li>
    </ul>
    

    Here the class first also comes together with the class item, but if we declare our CSS in the wrong order, that would not give the wanted behavior:

    .first { background: blue; }
    .item { background: red; }
    

    As you can see, the last matching selector will be used. It is the same as your example. No matter what is more logical, the 2 pseudo-classes are considered equal; thus the same rules apply and the last matching definition wins.

    Pseudoclasses are equals. It is the one defined last that wins! Here is a JSFiddle that proves my point :link defined after :hover, :link wins (test) so, your statement of :hover overriding :link is wrong, its just the same like with :active. It's all about the order.