CSS Specificity Scoring

Posted Jan 29, 2010 // 4 comments
Tobby :

Most folks realize what the "cascading" part of Cascading Style Sheets means for styling Web pages. However, some of the inner workings of CSS specificity are lost on many of them.

Specificity In General

First, a refresher in CSS specificity:

There are five sources of style definitions: Browser defaults, HTML Elements, Classes, IDs, and Inline Styles (six if you include user overrides). Each source takes a higher precedence over the previous. For instance, a header tag will have font-size and margins applied by the browser, but these are easily reset by simply declaring something like h2 { font-size: 24px; margin: 10px 0 0; } (an element selector) in your style sheet. This can be taken further with declaring h2.smaller { font-size:16px; }, which will shrink headers with a class of "smaller" (the margins will stay the same, however).

Like with most things, order matters. Especially when dealing with multiple external style sheets (common with just about any content management system, and especially with Drupal), the order that a CSS selector is declared makes a big difference. The latter that definition appears in the chain of selectors, the more likely it is to be the style definition that's actually rendered in the browser.

Selectors can be compounded in order to specifically target an element on a page. For instance, #left-column h2 { color: #900; } will cause certain headers in the left column of your page to be red, but they will otherwise keep any styles declared in h2 { ... }. All other header2 tags will be unaffected. This parent/child relationship is common.

However, the CSS large sites can get confusing fast. Selectors are redeclared for different page types, multiple modules might try to override each other, etc. It's important to understand how to quickly determine which selector will be used beyond simply re-ordering style sheets or nesting your elements.

How Specificity Scoring Works

Think back to grade school, when your teacher was explaining numbers' "places". You have ones, tens, hundreds, etc. CSS specificity works much the same way. Each type of CSS element has a different "place". The only real difference is that when a place reaches 10, it doesn't carry over to the next place.

  • HTML Element - Ones
  • Class - Tens
  • ID - Hundreds
  • Inline Styles - Thousands

The selector h2 has a specificity score of 1, while the selector #left-column h2 has a score of 101. So, even if #left-column h2 is declared before h2, styles in #left-column h2 will take precedence.

A more complicated example might be to compare the following:

Assuming this HTML:

<div id="content" class="page">
  <div id="left-column">
    <h2 class="red">My Header</h2>
  </div>
</div>

and this CSS:

#content #left-column h2 {
  font-size: 24px;
  color: #900;
}
body div.page div#left-column h2.red {
  font-size: 64px;
  color: #090;
  margin: 20px 0;
}

Plenty of developers will assume that because the second selector seems more specific and that it's declared last that the header tag will appear big and green. However, the header will be 24 pixels and Georgia Bulldog red.

This is because the first select has a higher specificity score. The first one has two IDs and an HTML element; for a score of 201. The second one has 4 HTML tags, a class, and an ID; for a score of 114.

However, it's also important to note that the header will have a 20 pixel vertical margin, since the first selector didn't declare any margin. Just because a style has a lower specificity score doesn't mean it's completely ignored.

About Tobby

Tobby Hagler recently joined Phase2 Technology as a senior developer. He has extensive experience with Drupal-based web sites. His skills range from interface development, to application layer engineering, to system architecture. He focuses ...

more >

Read Tobby 's Blog

Comments

by David Lanier (not verified) on Sat, 01/30/2010 - 13:51

Clear explanation

Thanks for the clear explanation of CSS specificity. It doesn't affect the score much, but in the 2nd paragraph, did you mean "The first one has two IDs and *an HTML element*" ?

by Tobby on Mon, 02/01/2010 - 08:16

Good catch

David, yes I did. Thanks for pointing that out. I've updated the post to reflect that. Good catch.

by Christoph Berendes (not verified) on Mon, 02/01/2010 - 10:58

Is there a CSS editor that highlights this?

Tobby - this is clear and useful. It suggests that it would be useful to have a tool that, for a given specific element in a web page, extracts all the css that might apply from a set of stylesheets, and sorts them in descending specificity order. Is there such a beast?

by Tobby on Mon, 02/01/2010 - 13:39

Firebug for Firefox

Have you tried the Firebug plugin for Firefox? It doesn't give you the specificity score, but it does a really good job of showing you what styles are actually being applied (as well as any styles that are overridden) and where they come from (CSS file and line number).

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
  • Allowed HTML tags: <a> <strong> <code> <p> <img> <ul> <ol> <li> <h2> <h3> <h4> <b> <u> <i>
  • You may insert videos with [video:URL]

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.