CSS Specificity Wars
NB: First published in 2005. Read the up-to-date version and see the latest demo.
Join me, and together we can rule the galaxy as father and geeks! In 2005 I saw Aaron explain how the specificity of CSS selectors is calculated in a way which I hadn’t seen before. Then I came across a problem while building templates for a new project where two selectors behaved differently to how I expected and I realised that I had not completed my Jedi training.
The Dark Side
My problem was a simple one, how to serve a transparent PNG to browsers which support transparency and a GIF to browsers which didn’t at the time, without resorting to hacks, something that we did a lot back then. Here’s my markup:
<div id="nav-supp">
<p><a id="a-02" href="">Top</a></p>
<!-- etc. -->
</div>
My CSS starting point:
a#a-02 { background-image : url(n.gif); }
a[id="a-02"] { background-image : url(n.png); }
I had assumed that a modern browser would see and apply both rules (with the second overriding the first) and that an older browser which does not understand attribute selectors would see and apply only the first, ignoring the second. I was wrong.
Modern browsers did not apply the PNG image as I expected. The reason? A standard ID selector wins over an attribute selector in terms of the cascade. Dagnammit! I know I should have read the specs, but somehow that particular pleasure had escaped me. If I had, I might have learned that:
ID selectors have a higher specificity than attribute selectors. For example, in HTML, the selector #p123 is more specific than [id=p123] in terms of the cascade.
Sith Lords
A little Googling uncovered some rather dry reading on the subject of selector specificity (resources below). First, let’s look back at what Lord Elasticus (Patrick Griffiths) wrote on the subject of specificity:
You give every id selector ("#whatever") a value of 100, every class selector (".whatever") a value of 10 and every HTML selector ("whatever") a value of 1. Then you add them all up and hey presto, you have the specificity value.
A selector’s specificity is calculated as follows:
- count the number of ID attributes in the selector (= a)
- count the number of other attributes and pseudo-classes in the selector (= b)
- count the number of element names in the selector (= c)
- ignore pseudo-elements.
Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity.
Too much! For me, the W3C really is in a galaxy far, far away! Maths was never my strong point, so to help me understand calculating specificity better I made a chart based on the following specificity (or Sith power) values:
Each character (selector) is given its own Sith power (specificity value) depending on how powerful they are in the ways of the Dark Side:
- A storm trooper (element selector) is less powerful than Darth Maul (class selector*)
- Darth Maul is less powerful than Darth Vader (ID selector)
- Darth Vader is less powerful than the than the Emperor (style attribute)
- The Death Star blows up everything
* Attribute selectors and pseudo-classes have the same power as a class selector.
Here’s a CSS Specificity Wars graphic for you to download, print, and stick on your wall.
Do not underestimate the power of the Dark Side
Amazingly, Star Wars helped me understand CSS better. Join me, and together we can rule the galaxy as father and geeks!
The 2005 version of this post was translated into:
- Brazilian Portuguese by Mauricio
- Dutch by Mark
- Danish by Michael
- Spanish by Ismael Celis.
Resources
- W3C
- CSS - Specificity - HTML Dog
- Juicy Studio: Selector Specificity
- HTML Help: CSS Structure and Rules
- Meyerweb: Link Specificity
Replies
-
#1 On October 7, 2005 02:06 AM Rubber Duck said:
I have to say Andy, never once has your amazing ability to equate the complex explanation with something so easy to follow let me down, you need to write books along these lines! As ever a fantastic breakdown of nerd stuff into easy to understand movie trivia. Cheers fella.
-
#2 On October 7, 2005 02:11 AM Dean Edwards said:
You pretty much got it there. Attribute selectors are Sith power 10 along with pseudo classes (hover, active etc). It is worth noting that you can always “bump” specificity by including an ID somewhere in the selector—giving it Sith power 100 if needs be. That’s why a lot of people give an ID to the document body. That way they can always bump CSS rules if they need. Sith power!
-
#3 On October 7, 2005 02:19 AM Colly said:
WTF is going on? I know it’s 2am, but I’m sure I just witnessed a madman attempting to explain speci.., specifif…, speficyfyf…, specificificfy (gasp) using Stormtroopers and that bloody Rastafarian rabbit from Star Wars. I think I’d better go to bed.
-
#4 On October 7, 2005 03:48 AM Eric Meyer said:
I hate to make things more complicated, young Padawan, but you are not a Jedi… yet.
Basically, your Sith Power numbers are misleading. A selector with 13 element selectors will always have lower specificity than one with a class and an element. The way you have them, they’d be written with Sith Powers of 13 and 11, but they’re really (0,0,13) and (0,1,1).
This is because the CSS1 and CSS2 specifications represented the numbers that way and then made an offhand comment about the numbers being in an infinite-base counting system. CSS2.1 adopts the comma separation to reduce confusion-- I think I had something to do with that, actually. See the latter half of Link Specificity for an early example of this notation.
Oh, and don’t forget that the universal selector has a specificity of 0,0,0. Because, you know—universe, stars, space. Yeah.
-
#5 On October 7, 2005 03:49 AM Jack said:
You are so. freakin’. awesome.
-
#6 On October 7, 2005 04:23 AM Ara Pehlivanian said:
Correct me if I’m wrong but wouldn’t this have worked just fine?
a#a-02 { background-image : url(n.gif); }
a#a-02[id="a-02"] { background-image : url(n.png); }I don’t know about all that math but to me, if you repeat the first selector’s pattern and add to it then the second one becomes more specific. N’est pas?
-
#7 On October 7, 2005 04:26 AM Nick said:
So what did you end up writing in your style sheet?
-
#8 On October 7, 2005 04:55 AM Justin Perkins said:
I would have liked to see OG figurines rather than the new school ones, but that is a wonderful analogy just the same. Whether or not you prefix your id/class selector with a tag name also plays a part in the specificity, I know it’s implied in this tutorial but I just wanted to mention it anyway (since it really threw me for a loop at first). I probably didn’t say that very well, so I’ll just resort to writing CSS instead:
p#sith{
color:#000;
}
#sith{
color:#f00;
/* this won’t be applied because of the higher specificty above */
} -
#9 On October 7, 2005 06:49 AM Natalie said:
This is a fantastic article. I’ve printed out your jpg and have it stuck to the wall next to my monitor. And it helped me fix a tricky issue I was having with my latest client site. May the Dark Force be with you!
-
#10 On October 7, 2005 07:10 AM Knut Karnapp said:
Fabulous way to combine Star Wars with math CSS.
-
#11 On October 7, 2005 07:38 AM Lachlan Hunt said:
Eric Meyer’s advise (comment 4) about using the commas is good, but using his examples: one selector with 13 storm troopers and another with 1 Vader and 1 storm trooper, the specificity shouldn’t be represented as 013 and 011, respectively.
13 storm troopers should be represented as a C (if we use letters as digits, like in hex), so their specificity would be 00C and 011, respectively, and thus the method still works. However, because most people have difficulty thinking outside of base 10 numbering, using the comma separator like 0,0,13 and 0,1,1 is much easier.
-
#12 On October 7, 2005 07:42 AM Khairudin Lee said:
Never underestimate the powahh of the darkside. As someone who’s weak in Math as well, this article was useful , in fact I understood the chart right away instead of the article. Kidding! Thanks for sharing Andy!
-
#13 On October 7, 2005 07:48 AM Heiko said:
Interesting Article. I’ll try it out!
-
#14 On October 7, 2005 07:53 AM Stuart Langridge said:
While I have a sort of twisted admiration for the Byzantine complexity of the specificity rules, the only occasion I ever get bitten by this is with IDs, so I have learned: ID selectors get to win. If you want other stuff to apply and it’s being overridden by an ID selector, add an ID selector to the other stuff. While the rest of it might, one day, cause problems, it hasn’t so far…
-
#15 On October 7, 2005 08:01 AM Andrew Vit said:
There’s another level of complexity to consider when you add the full complement of selectors in CSS2. What’s the unit value of a child selector? Sibling? Pseudo-class or pseudo-element? For example:
div#sith>p {} // child selector is more specific
div#sith p {} // than descendant selectorI suspect that the child selector adds 1 unit of specificity. (i.e., one stormtrooper.)
In addition to specificity, back up a bit and consider the bigger picture: don’t forget the whole cascading order! (Well explained here.)
Don’t underestimate the !important rule which should have been your trump card for the problem you ran into. The !important rules are given precedence, before normal specificity is even considered.
-
#16 On October 7, 2005 08:06 AM Alex said:
May the Type Be With You. I read about this topic in a CSS book, back in the beginning of my learning purposes. Found it really interesting, but I never used it, or thought about it while writing styles. But I REALLY do like your draft… nice idea to visualise the principle. Greetings from Germany. Alex
-
#17 On October 7, 2005 08:13 AM Andrew Vit said:
Eric’s post clears this up very well. I would also add a column to the left of her table to include !important rules… Sorry my previous reply got a little messed up: XHTML markup doesn’t work for comments! Here’s an added line break in case the above was unclear:
div#sith>p {} /* child selector is more specific */
div#sith p {} /* than descendant selector */(Fixed my CSS comment markup too. Duh.)
-
#18 On October 7, 2005 08:33 AM Malarkey said:
Eric: That is why you are the master and I am still the learner!
My training is still not complete obviously, but I’ve updated the Sith Power ratings accordingly. Now, where did I put that blaster?
-
#19 On October 7, 2005 09:05 AM brothercake said:
With !important I have become more powerful than any Jedi ;)
-
#20 On October 7, 2005 09:07 AM Kris said:
And of course a property tagged with the !important rule is more specific than any other selector, unless there is another selector (with the same property and an !important rule) that is more specific. It needs to be pointed out, though, that IE/Win ignores this !important rule when the same property appears twice within one selector. This makes for interesting CSS hacks:
a {
color: red !iportant; /* good browsers */
color: green; /* IE/Win */
} -
#21 On October 7, 2005 09:24 AM jontan said:
Whenever I hear “base (any number but 10)” in maths I am overcome with an urge to flee to the outer rim for sanctuary but instead, this padwan used his fear and overcame specificity with the help of Meyer and Malarkey. All that before breakfast. Thank you for your part comrade.
-
#22 On October 7, 2005 09:37 AM Phil Baines said:
Really good way of breaking it down. I already had a fairly good understanding of specificity, but this method of working it out using Sith Power will definitely help in the future. Also, I just noticed that you have left a tag open in your code. putting everything afterwards in italics. just after the “Ed says: Ingnoring inline syles.” Keep up the good work!
-
#23 On October 7, 2005 09:57 AM Ian Lloyd said:
You know what, I’ll still not remember the fine details of this, no matter how many storm troopers you put in front of me! But I have to say that it’s a very innovative idea you’ve come up with. Perhaps you could explain the offside rule, too.
-
#24 On October 7, 2005 10:16 AM Jens Meiert said:
Well, Eric already pointed out that your representation is flawed and not conforming to the specification ("12" might then be "0,0,0,12" or "0,0,1,2", where the latter one is of higher specificity). Also, where is the boss enemy, the “style” attribute? It’s like the Death Star then.
-
#25 On October 7, 2005 10:28 AM Malarkey said:
Thanks guys!
@ Brothercake: "With !important I have become more powerful than any Jedi ;)"
Is your lightsaber still glowing purple James?@ Ian: Mmmm, the offside rule? When an X-Wing fighter is further forward than the last Star Destroyer when the missile is fired, that’s offside.
@ Jens: I’ve amended the representation based on Eric’s clarification. And yeh, inline styles are like the Death Star. How sad are we? ;)
-
#26 On October 7, 2005 10:53 AM /T said:
Stormtroopers != Sith
-
#27 On October 7, 2005 11:18 AM Reuben Whitehouse said:
Bloody hell. Speci-what? Even more learning, I must do. Great article! Andy, genius money-making scheme: Specificity Wars duvet covers. Waddya think? For too long Pixar have dominated this market!
-
#28 On October 7, 2005 12:17 PM Peter Barnes said:
I will reluctantly admit to being a geek, but accepting you as a father is a step too far!! Great article though. Bemused looks from all as I picked up the poster from the print room, and nobody takes me seriously as it is :-(
-
#29 On October 7, 2005 01:06 PM Lakitu said:
This has to be one of the best and funniest explanations of the Death Star that CSS sometimes presents itself as. Great work, thanks!
-
#30 On October 7, 2005 01:45 PM Jesse said:
Wow. The Dark side is good.
-
#31 On October 7, 2005 02:12 PM Nick said:
I guess I’ll ask again. Malarkey, what did the final rules look like on your style sheet?
Thanks
-
#32 On October 7, 2005 02:44 PM Sally Carson said:
It could only have been nerdier if you had used Star Trek instead, this is pretty nerdy though. Pure Genius!!
-
#33 On October 7, 2005 02:44 PM Malarkey said:
@ Nick: Ooops, missed you there, sorry :( It looks like this now.
a#a-02 { background-image : url(n.gif); }
p>a#a-02 { background-image : url(n.png); }The CSS for the site is still very verbose and will be optimised later in the process.
-
#34 On October 7, 2005 02:48 PM M.e. said:
Screw cheat sheets, this concept could finally put the idea of WYSIWYG to rest. If I could whip up a glossary extension for BBEdit that would let me drag and drop Storm Troopers around my screen to facilitate markup and layout, my day would be 1000x better.
-
#35 On October 7, 2005 05:15 PM Alan Wyatt said:
Mmm, the Web Standards are strong with this one.. Now, I wonder if I can knock up a concept to use R2R2 and C3PO to explain the use of mathematical induction in recurrence systems or the composition of classes for my upcoming OU exam?
Alan
-
#36 On October 7, 2005 09:49 PM Chris Neale said:
Re: 35 Malarkey
You could have put it as :
a#a-02 { background-image : url(n.gif); }
a#a-02[id] { background-image : url(n.png); }
a#a-02[id] trumps p > a#a-02 : )And, I know precious little about selector specificity : ]
-
#37 On October 7, 2005 11:18 PM Pablo Impallari said:
Excellent! say no more…
-
#38 On October 8, 2005 02:14 AM Matt Robin said:
Great article…and use of star wars figures…the offside rule explained with X-Wings and getting Colly a bit befuddled at 2 a.m. :) (He’s more nuts than me: I saw it in the feed and left it until today because I knew it would have me gibbering and looking clueless too…nothing new there though…but worth avoiding!) I actually read Eric’s articles before this one…so it sort of made a bit of sense about the order of the specificities and such. Will I remember all of it by the time I wake-up? Hmmmm…bits and pieces—I’ll be back (wrong movie)…with a blaster.
-
#39 On October 8, 2005 01:30 PM Gerrit Kaiser said:
Nice explanation of specificity. The answer to your question, however, isn’t CSS. Testing for PNG support through testing for support for the attribute selector is a dirty hack that’s almost guaranteed to backfire. The HTTP "Accept:"-Header and Content Negotiation will be your friends.
-
#40 On October 8, 2005 02:38 PM Ariel Burone said:
Malarkey: There is a little error in the reply error chequer. It’s trying to load https://stuffandnonsense.co.uk/styles-site.css and it doens’t exists. ;-)(Ed says: "Thanks Ariel, I get the geeks into it.")
My original post: Feel The Power of the Dark Side!
-
#41 On October 9, 2005 04:28 AM Eugene TS Wong said:
Thanks for your explanation. Using CSS is a great way to explain how the Sith powers work. ;^) Seriously, thanks, because I was wrestling with this specific CSS problem and never understood this infinite base concept.
-
#42 On October 10, 2005 03:38 AM David said:
Fantastic! Posts like these is why this site is always in my favourites. Thanks for breaking it down!
-
#43 On October 10, 2005 08:38 PM Kevin Tamura said:
Oh gawd this is freaking hilarious. Oh, and ver useful too.
-
#44 On October 11, 2005 06:17 AM Dustin Diaz said:
I’m still with this comment.
Storm Trooper != Sith
-
#45 On October 11, 2005 06:56 PM Aaron Gustafson said:
You nerf herder. Very clever… only wish I’d thought of it first.
-
#46 On October 11, 2005 08:09 PM Anthony Ettinger said:
Excellent! I finally am starting to understand specificity!
-
#47 On October 12, 2005 08:04 AM Charles said:
TopStyle has a nice specificity feature, but it’s somewhat hidden. Go to Options (F8), then General › User Interface and in there you’ve got a “Show CSS specificity in selector list and related styles” option you can tick. You now get a extra column in your CSS Selectors panel with all the calculations done for you—nice!
I must admit, I never really understood what it was all about until this post, but now I do, so this option is staying permanently on in TS from now on.
-
#48 On October 12, 2005 11:56 AM Robert Wellock said:
Simple really.
-
#49 On October 12, 2005 05:14 PM jason said:
Although Stormtrooper != Sith…
Your chart is a good overview of specificity. (Not to mention quite funny).On comment #4, wouldn’t (0,0,0) be the equivalent of just the dark side of the force? How would you rate Yoda, Luke, or Obi-wan? Would they be represented by the negative side of the infinite-based system?
-
#50 On October 14, 2005 05:09 PM Luc Pestille said:
Impressive. Most impressive.
-
#51 On October 18, 2005 03:40 PM Eric Meyer said:
Important rules are not more specific than non-important rules. Importance is beyond specificity. It has power that specificity cannot possibly comprehend. I need to write an article.
-
#52 On October 18, 2005 07:03 PM Malarkey said:
@ Eric Meyer: "Important rules … [have] power that specificity cannot possibly comprehend."
So if i understand this correctly, !important is like ’force lightning’?
-
#53 On October 19, 2005 05:06 PM Chris Gilbert said:
Erm, where’s Yoda?
I feel a bit guilty talking Star Wars, sorry CSS Wars, without bringing my old buddy Yoda into the equation.