Forum Moderators: not2easy
To be honest: it works as most would expect it to work if you do it in that order. So why am I saying it might be time to say goodbye to that rule?
Bad code
yes it leads to bad code in many real life cases.
e.g.:
#menu a:link {
color:#000000;
background-color:#ffffff;
display: block;
float: left;
width: 120px;
height: 30px;
text-decoration:none;
}
#menu a:visited {
color:#000000;
background-color:#ffffff;
display: block;
float: left;
width: 120px;
height: 30px;
text-decoration:none;
}
#menu a:hover {
color:#000000;
background-color:#ffff00;
display: block;
float: left;
width: 120px;
height: 30px;
text-decoration:none;
}
#menu a:link {
color:#000000;
background-color:#ffff00;
display: block;
float: left;
width: 120px;
height: 30px;
text-decoration:none;
}
The masses of duplicate settings are not needed. All that was sought is to have the links render as some sort of a button and change the background-color on hover (active: honestly - who cares about the color for that fraction of a second as long as it doesn't blow up the design)
Luckily there are people who do the above with what they need only:
#menu a {
color:#000000;
background-color:#ffffff;
display: block;
float: left;
width: 120px;
height: 30px;
text-decoration:none;
}
#menu a:hover {
background-color:#ffff00;
}
So what's different here? Nothing much as such is different. The link is now styled regardless of the state it is in (and hence there is absolutely no need to style all of them) and if you care about a state, you can just change the things you want to change in the specific state.
prevents knowledge of cascade and specificity
The "rule" is not something you'll find in the CSS2.1 or CSS3 standard.
It is something intended to shield people from the concepts that are at the very core of CSS.
The cascade and the specificity are not the easiest concepts to grasp for a novice, but grasping them can be done easily enough through some simple examples.
E.g. when looking at the code above why can the rule with the selector "#menu a:hover" win over "#menu a":
Well the specificity of "#menu a:hover" is (0,1,1,1) the specificity of "#menu a" is (0,1,0,1).
So what happens:
- cascade: the element in the hover state not only gets the settings in the "#menu a" rule, but also those in the "#menu a:hover"
- specificity: those settings that are in disagreement (background-color) the setting with the highest specificity wins out.
But why is there need for an order to start with ?
In the 2nd example above the order isn't important at all (specificity determines what wins, not order). But if we wanted e.g. a hue of blue for links that have not been followed, a hue of purple for those that have been visited and a hover effect that changes the color of the test to bright red, order does come back into play.
So when does order come into play ?
When the specificity is the same the last rule wins on conflicting settings.
So what happens if we have :hover before :visited ?
Well a link that's not yet visited will work exactly the same as with the LoVe-HAte order.
The link that's been visited before will, when hovered, see the :hover rule and the :visited rule and want to apply both of them at the same time. Since they have the same specificity: if they have conflicting settings, those that are in the last rule will win out (non-conflicting settings will all be applied).
If it could be an unwanted effect or not. It all depends on what you want to happen!
origin of the "rule"
To be honest I asked fellow moderators for this as I didn't know it myself.
It seems there is a book published back in May 2003:
Designing with Web standards By Jeffrey Zeldman [books.google.com] (p.242) that not only uses the LVHA order, but also a mnemonic called Love-HA!
It credits the work of Eric Meyer on specificity [meyerweb.com] pointing out the order of LVHA and the reasons behind it.
I'm surely not accusing Eric of anything, and his article as it is today is far more than explaining.
But as we made the mnemonic itself into a rule, and forget to point out the basis on which that order is built, together with the other possibilities that might come from a different order, it does slowly become a problem.
prevents creativity
Already above I pointed out that what you want to happen could be served with a different order of the rules (E.g.: preventing the hover from popping up a box inviting the users to click on an already visited link: yes it can be done)
The different pseudo states a link can be in, are also not mutually exclusive. E.g. a link can be visited and hovered at the same time.
So, how about styling the hovering over a link that's visited or not differently ?
All you need is:
#menu a:link:hover {
/* ... */
}
#menu a:visited:hover {
/* ... */
}
Now why don't we see these rules all that much (if at all)?
- There's IE6 that doesn't support multiple classes nor pseudo classes. (easily fixed with e.g. IE7.js)
- And there's the lack of a widespread knowledge such things are possible to start with.
But the "rule" makes it harder than needed to get people to experiment and think beyond the obvious.
:focus ?
Focus ? Yes, that's a pseudo class in CSS2.1 too! And it can be styled just as well. Keyboard users might see it more than mouse users, but regardless the "rule" gives no guidance whatsoever.
So if we do need a "natural" order what would be a good suggestion ?
Eric Meyer suggests:
LVHFA [meyerweb.com] as the most natural order.
Yes, we could search for a new mnemonic and create a new one and still not tell people why we find it a logical order for most ways we like to interact with users. [Eric Meyer does explain it, but if we start to propagate the mnemonic as a rule it'll all be gone again]
CSS3 selectors
CSS3 is (in the process of) adding more pseudo classes. e.g: :target
Are we ever going to find a "natural" order if we have a dozen states we could use ?
And are we going to specify the entire truckload of settings in each state one after the other ?
Or are we going to use a base setting and then change what we need changed in those states we care about ?
As CSS3 modules each could potentially add more pseudo classes, are we going to change our mnemonic every so often (and make it longer every time) ?
An example of such a pseudo class introduced by CSS3 is :target [webmasterworld.com]. And yes, your menu might use the :target to find out e.g. which item to highlight as current.
Why now ?
IE6 is finally slowly dying out. So we can use more creativity (even if we fall back on a less desirable -but workable- solution for IE6. The additional possibilities could be used to enhance the experience for the other users (which are -by far- the majority of our users).
CSS3 is on the horizon offering us even more possibilities.
So are we ready to learn more about cascade, specificity, etc. or are we going to limit ourselves with a LoVe-HAte rule that was a good thing in CSS1 more than a decade ago ?
Sure it's more complex to explain it -and understand it- than to point to a rule that really isn't one, but we're here to learn aren't we ?
[edited by: swa66 at 2:02 pm (utc) on Oct. 18, 2009]
Great coverage - thanks!
When I first started, I'd occasionally put :hover before the 'a'... stunned why it didn't work. Found a blog post stating "hover must come last"... so I've always followed that guideline. Otherwise, I always style 'a' as the default link. Most of the time, I never need (or want) to touch 'visited' or 'link'. And if I do, I just add them. I agree... adding them for the sake of it and bloating it with excess seems bad practice.
However... I'm of the opinion that IE6 is dead. Most of the sites I work on today require up to date browsers (for Javascript, CSS, etc). I have no issues with IE8 and occasionally have to hack for IE7. But I have finally come to the conclusion that it is time to force those still running IE6 to upgrade; on some of my sites, if you come onto it running <=IE6, you get a nice notice telling you your browser is old, outdated, and incapable of modern internet usage, time to upgrade to IE8, Firefox, etc. Not something I would employ on every site, but the idea of spending time and effort placating a dead browser seems pointless.
#menu a:link,
#menu a:visited,
#menu a:hover,
#menu a:focus,
#menu a:active {
color:#000000;
background-color:#ffff00;
display: block;
float: left;
width: 120px;
height: 30px;
text-decoration:none;
}
#menu a:visited {
color:#666666;
}
#menu a:hover {
text-decoration:underline;
}
#menu a:active {
background-color:#ffff33;
}
etc.