Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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:

  1. 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?
  2. 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.

like image 835
Susam Pal Avatar asked Sep 10 '11 12:09

Susam Pal


2 Answers

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...

like image 85
BoltClock Avatar answered Oct 28 '22 08:10

BoltClock


This is how I understand it. All these pseudo classes have same specificity, so the pseudo class written at last wins. Now what do pseudo-classes :link, :visited, :focus, :hover, :active do? Let us see one by one.

a: link{color: red} tells the user agent to color the anchor element red in any state. Run the following script:

  a:link {
  color: red;
  
  }
<a href="www.stackoverflow.com">Go to stackoverflow </a>

The anchor element is colored red in the following states if and only if the link is unvisited,

  • Unvisited
  • hovered
  • Focused(Tabbed)
  • Active(Clicked)

So, a: link{color: red} tells the user agent to give red color to anchor element in all of the above states. Now let's compare it with a:hover pseudo-class. Run the following script

a:hover {
  color: red;
  
}
<a href="www.stackoverflow.com">Go to stackoverflow </a>

The anchor element is colored red in the following states,

  • hovered
  • Active(clicked)

We see that both :link and :hover pseudo classes are capable to define the hover state -- So if you assign these two pseudo-classes to a particular element then the one mentioned at last in the css file wins. This is the reason we say :link will override :hover when the former is mentioned below the later. The same concept holds for other pseudo-classes. I'd like to give list of what every pseudo class do.


a:link {...} sets the following states of an unvisited link
- Focused(Tabbed)
- hovered
- Active(Clicked)

link state will override every other state.


a:visited {...} sets the following states of a visited link:
- Focused(Tabbed)
- hovered
- Active(Clicked)

a:visited {...} will override every other state except :link if and only if the link has been visited.

Note that visited means it must be considered visited as per user agent's cache. E.g. a website visited 10 days ago might not be in user agent's cache then it'd be technically considered unvisited.


a:focus {...} sets the following states for both visited and unvisited links:
- Focused(Tabbed)
- hovered
- Active(Clicked)

a:focus {...} overrides :hover and :active states.


a:hover {...} sets the following states to both visited and unvisited links:
- hovered
- Active(Clicked)

a:hover {...} overrides :active state


a:active {...} sets the following states for both visited and unvisited links:

  • Active(Clicked)
like image 39
user31782 Avatar answered Oct 28 '22 09:10

user31782