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,
:link
has always been the default (untouched),- Then when a User points to the button, then that is where
:hover
comes into play. - 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.
精彩评论