开发者

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

The title basically says it all.

Suppose 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. So, I've tried this:

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

As it turns out, this doesn't work. After a lot of head-scratching, 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).

开发者_JS百科

Here's the fiddle: http://jsfiddle.net/V5FUy/


My question: 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.


yes this is expected behavior,

lets 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 mather what is more logic, the 2 pseudo-classes are concidered equal, thus the same rules apply the last matching defenition wins.

edit

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, its all about the order.


The active state must be declared after the hover state, in your CSS you're clumping together the active state before the active state so it's not being triggered.

If you state the proper order of operation it works, like below, it works fine.

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

a.noworks:hover {
    background: green;
}

a.noworks:active {
    background: red;
}

So, to answer your question, yes this is the expected behavior.

Here is the order of operation:

a:link
a:visited
a:hover
a:active


Because in the first code you defined :hover after you defined :active, so :hover "overwrote" :active. In the second, it's the other way around, :active overwrites :hover.


EDIT:

Sorry, I misunderstand the question.

Basically when you are in active state (with a mouse pointer) you are actually in hover state too. So based on CSS rules it would read the last one in stylesheet.

When you hover over a link and hold down the mouse key It's like this if we take pseud classes as normal classes :

<a class="active hover"></a>

So if your css was

.active{color:green}
.hover{color:red}

it would apply red

but if your css was

.hover{color:red}
.active{color:green}

It would apply green

From W3C

a:link    { color: red }    /* unvisited links */
a:visited { color: blue }   /* visited links   */
a:hover   { color: yellow } /* user hovers     */
a:active  { color: lime }   /* active links    */

Note that the A:hover must be placed after the A:link and A:visited rules, since otherwise the cascading rules will hide the 'color' property of the A:hover rule. Similarly, because A:active is placed after A:hover, the active color (lime) will apply when the user both activates and hovers over the A element.


This is how it works, and I'll try to explain why. As we know CSS will continue searching the document when applying styles and apply the style that is most specific to the element.

Example:

li.betterList { better list styling here }

Is more specific and will overwrite

li { list styling here }

And these Puesdo selectors are all considered the same specificity and thus the last line will overwrite the previous one. This is confirmed by the note on W3Schools

Note: :active MUST come after :hover (if present) in the CSS definition in order to be effective!

you can also throw this CSS on your jsfidle and watch it overwrite since they are the same specificity

.works {background: red}
.works {background: green}


This is the expected behavior in so far as most people always place the :hover pseudo-class at the end of the group of rules.

Order of declaration matters with pseudo-classes (see more here: http://reference.sitepoint.com/css/pseudoclasses), so the final rules get precedence, as with other rules in CSS.

For most people, I think the desired behavior:

a:link {
  ⋮ declarations
}
a:visited {
  ⋮ declarations
}
a:hover {
  ⋮ declarations
}

Since the :active is not so useful it is left out... or combined with a:link and a:visited... and then it is overridden by a:hover

W3C spells it out here:

Note that the A:hover must be placed after the A:link and A:visited rules, since otherwise the cascading rules will hide the 'color' property of the A:hover rule. Similarly, because A:active is placed after A:hover, the active color (lime) will apply when the user both activates and hovers over the A element.

http://www.w3.org/TR/CSS2/selector.html#dynamic-pseudo-classes

Even W3schools gets this one right:

Note: a:hover MUST come after a:link and a:visited in the CSS definition in order to be effective!!

Note: a:active MUST come after a:hover in the CSS definition in order to be effective!!

http://www.w3schools.com/css/css_pseudo_classes.asp


I think you should at least consider the flow of User Interaction on links (or buttons).

Usually,

  1. :link has always been the default (untouched),
  2. Then when a User points to the button, then that is where :hover comes into play.
  3. Once a User points to the link or button, then he/she will click, that is where :active comes in.

That is the standard sequence of how we interact with links (or buttons). With the exception of :visited, where the result is only obvious when the User has previously pressed the link.

It would be really helpful if you keep in mind the mnemonic: ' L o V e H A t e ' when dealing on links (except for :visited, which doesn't work for buttons).

However, if you really want to do an override, say, you want to change the color of a link that was already visited on active state, you can do something like:

a:visited:active {
     color: red;   
}

But the bottom line is, avoid changing the standard sequence if it's not necessary.


You can have the :active pseudo-class override the :hover pseudo-class regardless of the order of declaration by using the :not() selector.

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

a:hover:not(:active) {
    background: green;
}

This way, the :hover selector is triggered only when the :active selector is not.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜