Why Does .Foo A:Link, .Foo A:Visited {} Selector Override A:Hover, A:Active {} Selector in Css

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

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

Why must a:hover come after a:link and a:visited in the CSS?

Because there is a priority order.

if hover was before visited, then hover wouldn't get ever applied, because it would be "forever" overwritten by visited style (if it has been really visited), that was applied after.

Same goes for :active (mouse down) - if it's defined before hover, then hover will always overwrite :active(mouse down)

Makes sense?


On the other hand, this is just "conventional rule" - it is not forced. If anyone wants to have :visited higher priority, overriding :hover/:active - you are free to do so - it simply would be just unconventional


And lastly, it is not only order that plays the role of style priority.

Elements that are more explicitly defined have higher priority.
Styles that are !important will have higher priority than explicitly defined styles.

Explicitly defined styles with !important and set last will have "ultimate" priority.

To question "Why would you want to use these to override styles? Wouldn't it be better just to make styles in your CSS file correctly ordered?" - Reason to use overrides by more explicit definition and !important priority overrides comes handy when you use large css/theme/bootstrap, that you haven't created and you have to quickly override/change some stuff... These dirty overrides come as a quick/cheap (not very pretty) solution.

.theBad:active {  color: red;}
.theBad:hover { color: green;}
.theGood:hover { color: green;}
.theGood:active { color: red;}
<a href="#" class="theGood">the Good</a> - this will turn red on mouse down<br /><a href="#" class="theBad">the Bad</a> - this poor little thing will not
<!--#ordermatters, The Ugly is lurking somewhere in the shadows-->

Why do anchor pseudo-classes a:link, :visited, :hover, :active need to be in correct order?

There is a detailed description here:

http://meyerweb.com/eric/css/link-specificity.html

It is related to CSS specificity.

Citing from there:

All of them can apply to a hyperlink, and in some cases, more than one will apply. For example, an unvisited link can be hovered and active at the same time as it's an unvisited link. Since three of the above rules apply to the hyperlink, and the selectors all have the same specificity, then the last one listed wins. Therefore, the "active" style will never appear, because it will always be overridden by the "hover" style. Now consider a hyperlink which has been visited. It will always and forever be purple, because its "visited" style beats out any other state, including "active" and "hover."
 
This is why the recommended order in CSS1 goes like this:

A:link

A:visited

A:hover

A:active

BTW W3 Schools is not the best resource for formal definitions. You are better off going to the source, at w3c. For example, it is not "vitally important", but it is recommended.

why “a:hover MUST come after a:link and a:visited(w3school)”?

Pseudo-classes must be declared in a specific order.

The mnemonic LoVe HAte is always useful for remembering the correct order:

:link
:visited
:hover
:active

Each pseudo-class corresponds to an event which can only happen later in the timeline than the one before.

That is to say:

  1. A link is unvisited before it is visited.

  2. A link is visited before it is hovered over.

  3. A link is hovered over before it is in active use.

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

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.

Why a:hover does not work , if it is not declared in correct order in style sheet?

This is how CSS works (order is important). For styling links the order for pseudo-classes is:

  1. Link (applied if you have not visited this URL)
  2. Visited (applied if you've visited the URL the href points to)
  3. Hover (applied if the mouse is hovering over the tag)
  4. Active (applied if you are interacting with the tag - pressing mouse down, etc)

The reason why order is important is because of CSS Specificity. The rules you've written all have the same specificity, and therefore will be affected by order (rules written last will override earlier written rules).

Note that :hover will not work with those using a keyboard. You can provide those users with the same experience by using the :focus pseudo-class.

a:link {  color: blue;  text-decoration: none;}
a:visited { color: purple;}
a:hover,a:focus { text-decoration: underline;}
a:active { color: red;}
<a href="#">This is a link</a>

One style selector to specify both hover,active within a specific class

Your code actually has one other problem: the first set of CSS rules are not being grouped correctly. You need to repeat the #main-nav ul li portion for every selector in the list; otherwise, the rules will apply to other links in the document, not just the ones in #main-nav ul li.

In the same vein, to group your last two rules you need to group their selectors in their entirety.

Also, in case you weren't aware of it, you probably want to follow the LoVe-HAte mnemonic in arranging your link pseudo-classes, unless you have a good reason to sort :visited after :hover and :active (I've also taken the time to arrange your last two selectors in the same order).

/*Apply the following styles to anchor tags within any ul within #main-nav*/#main-nav ul li a:link,#main-nav ul li a:visited,#main-nav ul li a:hover,#main-nav ul li a:active {    color: #fff;    text-decoration: none;    padding: 10px;    display: block;    border-radius: 4px;}/*Apply the following styles to anchor tags within .menu only within #main-nav*/#main-nav .menu a:hover,#main-nav .menu a:active {    background-color: #ccc;}
<div id="main-nav">    <ul class="menu-switch">        <li><a class="js-menu-toggle" href="#">OPEN ME</a></li>    </ul>    <ul class="menu">        <li><a href="#">Menu item 1</a></li>        <li><a href="#">Menu item 2</a></li>    </ul></div>


Related Topics



Leave a reply



Submit