The Great Specificity Swindle!

Recently I’ve been working on a SitePoint project: The Ultimate CSS Reference (Coming soon! If you’re into CSS it’s going to rock your world). While researching the shadowy corners of the web for traces of arcane CSS lore, I’ve realized that a lot of information about CSS on the web is in dire need of an update.

Between 2001 and the present we’ve had an explosion in knowledge and general understanding of CSS, the web is full of tutorials, articles and blog posts written during this era of enlightenment. But, time moves on and browsers improve. The level of CSS support in modern browsers is pretty darn good and just as an intimate knowledge of CSS hacks is fast becoming redundant so is a lot of that material. In fact, some of it is down right misleading and your search results are bound to be chock full of well intentioned, but out-of-date information.

Among the pages of arcane CSS lore you’ll find something called the CSS cascade; the thing that ultimately decides what each element’s style will eventually be. It has a reputation for being difficult to understand and is often the cause of those frustrating, obscure CSS problems when what happens in the browser is nothing like what you were expecting to happen. The amount of misinformation on the web certainly doesn’t help, so this is my small effort to correct the situation: putting to rest two of the biggest myths about the CSS Cascade.

Myth: Embedded styles take priority over external styles and inline styles take priority over embedded styles.

As far as browsers are concerned it makes no different how CSS is linked to a document; all three of these methods are considered to have the same origin: the author style sheet. What causes one to overwrite the other has nothing to do with how they are linked to the document.

If importance and specificity are equal the only thing that matters is source order; when a style sheet link element appears after the style element (the embedded style), in the document’s head, the external styles overwrite the embedded styles. I think this myth developed because generally people put their link elements before their style elements.

Inline styles overwrite identical style declarations in other style sheets only because they have a higher specificity (see below), but important declarations (see below as well) overwrite inline styles no matter where the declarations come from—even external style sheets.

Myth: Specificity can be represented by a total score.

You’ve probably seen this formula before:

specificity = number of IDs * 100 + number of classes * 10 + number of elements * 1

So a selector like p.introduction would have a selector score of 11 (10 + 1). While certainly easy to understand it can be very misleading; you may begin to think that if you have 10 element names in your selector then it’s equivalent to 1 class name and that’s just plain wrong. This myth is probably the legacy of the badly worded explanations in the older CSS1 and 2 specs.

1 ID selector will always have a higher specificity than any number of class selectors, even a million class selectors! Once the cascade reaches the point of having to sort two or more property declarations by specificity, it does so like this:

  1. Is one an inline style? It wins! If none are inline proceed to b.
  2. Count the number if IDs in the selectors. The highest score wins! Same score? Proceed to c.
  3. Count the number of attributes, class names and pseudo-classes. The highest score wins! Same score? Proceed to d.
  4. Count the number of element names or pseudo-elements. The highest score wins!

If they have the same score in the last step then they have the same specificity and source order dictates which one wins (the one that comes last in the source).

The CSS2.1 specification would have expressed the result of the counting above in the form a,b,c,d (a = 1 if true, 0 otherwise). So an inline style has a specificity of 1,0,0,0 while a selector like p.introduction has a specificity of 0,0,1,1 (one class and one element name). You can’t just remove the commas.

This also puts to rest a few other minor misconceptions:

  • Wrong: A child selector like div>p has a higher specificity than a descendant selector: div p. From the process above you can see that combinators are not even included; they make no difference. Those two selectors have the same specificity 0,0,0,2 (2 element names). The universal selector: *, is also ignored.
  • Wrong: A selector like #someid has a higher specificity than p#someid because the ID selector comes first. The order makes no difference, just count the number of components in the selector. #someid has a specificity of 0,1,0,0 and p#someid has a higher specificity of 0,1,0,1.
  • Wrong: an !important declaration has a higher specificity than a normal one. As you’ll see below, specificity has nothing to do with it.
  • Wrong: an inherited property has a lower specificity than a declared one. Again, as you’ll see below, specificity has nothing to do with it. In fact inheritance has nothing to do with the cascade at all!

Gettin’ Cozy With The Cascade

The CSS cascade is easier to understand than you think, and once you get it, your understanding of CSS takes a huge leap.

Here’s the cascade in 4 simple steps; this is the process that occurs for each CSS property for each web page element:

  1. Gather all the declarations for the property from all sources. This includes default browser styles and custom user styles, as well as author style sheets. If there is more than one, proceed to 2.
  2. Sort the declarations by importance and origin in the following order (from lowest to highest priority):
    1. user agent style sheets (default browser styles)
    2. normal declarations in a user style sheet (a user’s custom style sheet)
    3. normal declarations in an author style sheet (web page style sheets; external, embedded, and inline styles)
    4. !important declarations in an author style sheet
    5. !important declarations in a user style sheet

    The one with the highest priority wins. If more than one have the same priority then proceed to 3.

  3. Sort by selector specificity (see the process above). The one with the most specific selector wins. If no clear winner, proceed to 4.
  4. The one that comes last in the source wins!

If the cascade does not set a CSS property on an element, then the browser will fall back to using an inherited property from the element’s parent (this only happens for some properties), otherwise the property is set to the CSS default value.

That’s it! Not too difficult eh? Now you understand something about CSS that once only the gurus knew! Now, if you’re game, get up and dance a jig to celebrate. I certainly did!

*runs around with t-shirt over head, hands in the air, screaming WOOOOHOOOOO!*

OK, try not to picture that in your head…

If you want to really get to know CSS in a way that won’t melt your brain try the SitePoint video: The CSS Video Crash Course.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.sitepoint.com/ Kevin Yank

    This is awesome stuff, Andrew! Great to get this published, as I totally agree – there’s a lot of bad advice out there.

    More sneak previews of The Ultimate CSS Reference coming soon, folks!

  • Shady

    I’ve been in web development since 2000, working on PHP, ASP and ASP.net apps, and I have never, ever come across any of these myths, despite working in some environments that should have made the front page of http://www.worsethanfailure.com

  • Laura

    Brilliant. That is such a clear and succinct explanation.

  • http://www.domedia.org/ junjun

    I’m with Shady here. Are these purely internal SP myths or is it possible to point in a general direction where one might find these myths alive? ;)

  • http://tetlaw.id.au atetlaw

    junjun and Shady, the important thing was that you might have learned something new about the cascade and specificity. Was it helpful?

    In regards to the ‘myths’, yes I may have used the tiniest little bit of hyperbole there, but do a search for ‘css cascade’ or ‘css specificity’ and you’ll easily find a dozen websites promoting them.

  • http://www.sitepoint.com Simon Mackie

    “Specificity” is just about the most tongue-twistingest word, ever :-)

  • http://www.tyssendesign.com.au Tyssen

    I’ve come across both those myths before and not only on Sitepoint.

  • http://chris.unigliding.co.uk Stormrider

    I’ve come across them as well, but I knew how it worked. I’m glad you cleared up the 100x + 10y + z way of calculating specificity – that only works if there are less than 10 of each type of selector!

  • kL

    I have come across some of these myths. They’re not popular because most webmasters don’t even have slightest clue about cascade/inheritance and they use only class selector for everything :)

  • BrianW

    Well the total score myth I believe is in O’Reilly’s CSS Definitive Guide.

  • Eric Meyer

    The summation myth is present in the first edition of O’Reilly’s Definitive Guide, but not the second or third editions. That’s because I found out about all this between the first and second editions, settled on the comma notation as a way to disambiguate the situation (I tried hyphens first but didn’t like the result), and pushed its use until it got into the CSS2.1 specification.

    So yeah, my bad, but hopefully I made up for it subsequently!

  • http://www.sitepoint.com/ mattymcg

    “Specificity” is just about the most tongue-twistingest word, ever

    Second, only, to “tongue-twistingest”…

  • http://www.calcResult.co.uk omnicity

    So where is the swindle? Did I skip a bit by accident?

  • http://www.eirestudio.net babyboy808

    Thank god Shady said something first. I totally agree, SP propoganda :)

  • Jens Meiert

    Sounds like panic everywhere …

    Myth 1 is certainly just one out of a many things that might be considered “mythical” by CSS novices; myth 2 has fortunately been fixed (read: clarified) by CSS 2.1, that is right.