Why does .foo a:link, .foo a:visited {} selector override a:hover, a:active {} selector in CSS?

css, css-selectors

Solution

When you first started with CSS, you might have learned about the LoVe-HAte mnemonic for the order in which to specify link selectors (`a:link`, `a:visited`, `a:hover`, `a:active`). Have you ever wondered why this mnemonic was chosen?

Well, there's a note in the spec on how the link and dynamic pseudo-classes are treated when multiple rules using all of them apply to the same element, which explains why you need to set link selectors in that order:

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.

Anyway, the point I'm trying to make above is that all four pseudo-classes, being pseudo-classes, have equal specificity. Everything else about specificity applies. In this case, out of a bunch of equally specific selectors, the last rule is applied. When or how each pseudo-class is triggered is never relevant.

Now, the simple introduction of the `.foo` selector causes your second set of link/visited rules to override your first set of link/visited styles and the hover/active styles, forcing links in elements with that class to always appear green until you add hover/active styles with the `.foo` selector.

Sorry if my answer seems stitched-up or slipshod by the way, I'm typing this on my iPhone right now and it's pretty hard to think out here...

Problem

Sample code: http://jsfiddle.net/RuQNP/ ``` <!DOCTYPE html> <html> <head> <title>Foo</title> <style type="text/css"> a:link, a:visited { color: blue; } a:hover, a:active { color: red; } .foo a:link, .foo a:visited { color: green; } /* A possible fix */ /* .foo a:hover, .foo a:active { color: red; } */ </style> </head> <body> <div class="foo"> <a href="http://example.com/">Example</a> </div> </body> </html> ``` What I was expecting: The link would appear red on hover. What I get: The link appears green on hover. Questions: - Why does the `color` defined in `.foo a:link, .foo a:visited` selector override the one in `a:hover, a:active`? What's going on? - I understand that I can fix it and get what I expect by uncommenting the commented code. However, I want to know how can we correct the `.foo a:link, .foo a:visited` selector such that it does not override the `color` defined in `a:hover, a:active`? If I understand http://www.w3.org/TR/CSS21/cascade.html#specificity properly (Thanks, BoltClock), this is the specificity table for the various selectors in the code. ``` a:link - 0 0 1 1 a:visited - 0 0 1 1 a:hover - 0 0 1 1 a:active - 0 0 1 1 .foo a:link - 0 0 2 1 .foo a:visited - 0 0 2 1 ``` So, the style defined for `.foo a:link` overrides the style for `a:hover` when both `link` as well as `hover` pseudo-classes apply to an A element of class `foo`. Similarly, the style defined for `.foo a:visited` overrides the style for `a:hover` when both `visited` as well as `hover` pseudo-classes apply to an A element of class `foo`.

Original source

Related problems