Understanding CSS Specificity

Specificity can be tricky. Well, tricky to say the word, anyways. There's a quick approach that I use that can hopefully help you out.

Types of selectors

There's a whole bunch of selectors but for our purposes, we can break it down into three types, of increasing importance:

  1. Element selectors (and pseudo-element selectors) Eg. p {color:red;}
  2. Class selectors (and attribute selectors) Eg. .myclass {color:red;}
  3. ID selectors. Eg. #myid {color:red;}

When it comes to specificity, it just takes one class selector to override any style declared with just element selectors, and it takes just one ID selector to override any style declared with class and/or element selectors. Let's check out an absurd example:


<style type="text/css">
#contact b {color:blue;}
div.help b {color:green;}
body div p b { color:red; } 
</style>
<body id="contact"><div class="help"><p><b>my example</b></p></div></body>

In this case, my bold text would be blue because the ID selector has more power than the element or class selectors in the other two rulesets.

Solving Specificity

If you're having specificity issues, there's some quick ways to solve it. First, avoid !important. I hear of people having to use !important all the time and you should I almost never have to. !important can complicate matters in that it requires you to declare another style using !important with the same or higher specificity as before. !important is a last resort. Consider it akin to inline styles (since they have similar power). The problem is that once you've used it, the only way to override it is to specify it on a style after you've declared the first one.

Next, whenever declaring your styles, use the least number of selectors required to style an element. Doing html body div p.intro is a little verbose if .intro will do. Now, if you run into a conflict, you need to increase specificity. If the style required is after the first declaration then all you have to do is match specificity. So, if the first ruleset had a class and two element selectors, all you'd need to do is have a class and two element selectors on the second ruleset to have precendence. Two class selectors or one ID selector would also have a higher specificity. If you need the first declaration to have precendence, then you'll need to exceed the specificity of the second style.

Using our previous example, if I wanted the text to be green, I'd have to add at least one ID selector to the middle ruleset.

If you're still having problems, you can always fall back on Andy Clarke's Specificity Chart.

Published August 23, 2006 · Updated August 23, 2006
Categorized as HTML and CSS
Short URL: https://snook.ca/s/647

Conversation

24 Comments · RSS feed
Craig C. said on August 23, 2006

Nice primer. Specificity is one of the more difficult concepts to grasp in CSS.

Another good thing to remember is that specificity is cumulative when one selector is made up of several selector types.

"div p" is more specific than "p".

"#home #content" is more specific than "#content".

"#content p" is also more specific than "#content", as is "div#content".

And so on.

And note that pseudo-class selectors have the same specificity as class selectors, so "a.contact" is equal to "a:link". With rules of equal specificity, the cascade takes over and they're applied in the order in which they're written.

Bramus! said on August 23, 2006

Heh, was gonna refer to Andy Clarke's Chart, because it's very straightforward. Learnt about specifity in his post on the matter (and the chart of course). After a while it's just plain easy.

And for those who are wondering how specifity behaves with the CSS 2.1 selectors ... (thus one could wonder «is "#parent>#child" (Child Selector) more specific than "#parent #child" (Descendant Selector) ?»):

div#sith>p {} /* child selector is more specific */
div#sith p {} /* than descendant selector */

wbr,
B!

EJ said on August 23, 2006

Informative post. I could definitely benefit from cleaning up my CSS. I tend to style sometimes in a 'quick-fix' approach to simply get the job done, and don't always think about cleaner, more elegant methods.

said on August 23, 2006

IE WIN has probs with specifity:

http://www.brunildo.org/test/IEASpec.html

Matt Turner said on August 23, 2006

Sometimes i've a little more verbose for the sake of clarity, e.g. ul#nav (as opposed to just #nav) reminds me my nav is an unordered list.

Another thing to remember, it's not just counting points. It's about just how specifically you're nailing a style. So the longer the selector, the greater specificity, and the narrower the scope. (in general)

Jonathan Snook said on August 23, 2006

Craig/Bramus: Thanks for the additional clarification.

Matt: I used to do that, too, but have found that I tend to use similar naming conventions from project to project so I usually know what element it applies to. The other thing, is that I use an indented approach (see my stylesheet) that would provide additional clues as to source location.

Mark said on August 23, 2006

I think a good rule of thumb for justifying !important is if you're overriding inherited CSS that you can't modify or have no control over. Legacy code that doesn't apply to a new template, CMS code, etc.

Nate K said on August 23, 2006

This is a very informative post. For me, indenting is what helps the most - as it gives me more information about the specificity. Also, having an organized stylesheet helps as well - for easy find for specific styles (layout, links, lists, etc).

Taking advantage of this helps keep your code cleaner and your presenation easier to maintain. Instead of spans and divs all over the place, you can group accordingly by ID or even body/html.

Each job is different. I take an 'inventory' of the styles I use and WHERE they will be used, then I can create them accordingly in the stylesheet. If I KNOW a certain element will only be in the footer, I dont need to declare a specific style - but can use an element selector. If there are styles that are used in many different places, I will make them more 'global'.

Klaus Hartl said on August 23, 2006

Jonathan, you forgot about pseudo-classes like :link, :visited etc. which also adds 1 to the specifity at class/attribute selector level.

a:link:visited will override a:visited.

Wow, your comment system is really smart.

Klaus Hartl said on August 23, 2006

Bramus, thats not true. Combinators like '>' and '+' do not add to specificity.

div#sith>p and div#sith p have the same specifity!

The universal selector '*' is also not counted for specificity.

Jeremy said on August 23, 2006

I've found that if you don't keep up with CSS, you tend to forget things. Updating my website to a new version, I have problems with things like this, even though a year ago I had it down pat. Thanks for the reminder.

Elliot Swan said on August 23, 2006

Sometimes I will use multiple selectors when they aren't required simply because 1) it allows me to see what I'm referring to when I go back later on and 2) I can get by with using fewer id/classes. When you're using multiple selectors to target specific elements, often you won't have to worry about selectivity because you just solved it when targeting those elements.

If it still is a problem, you can always just add "html body" at the beginning of your selectors.

Like Matt, I also will usually use something like div#wrapper rather than just #wrapper, as it allows me to see what types of elements I'm working with without having to go back to the XHTML.

Jens Meiert said on August 23, 2006

(Only scanned comments.)

> First, avoid !important. [...] The problem is that once you've
> used it, the only way to override it is to specify it on a style
> after you've declared the first one.

I'm sorry, but this is wrong. A more specific selector an analog declaration declared as !important suffices.

In general, !important doesn't need to be avoided if used wisely. I find that more appropriate than completely advising against !important rules.

Jonathan Snook said on August 23, 2006

Jens: I've updated the post accordingly. I still recommend against using !important as I still feel it makes things unnecessarily complicated. Also, I used words like "avoid" and "almost". Certainly there are times when it makes sense to use it and you can continue to do so. I just think that for troubleshooting, it's easier not to use it. (which is why I also recommended using as few selectors as possible; I find it easier to troubleshoot when I do)

Chris said on August 24, 2006

Thanks for that, Jon, great information. As Jeremy said it's easy to forget this stuff over time.

Carlos Eduardo said on August 24, 2006

Very nice article!

I'll post about CSS specificity on my blog too.

Thanx for the help with it =)

Johan said on August 24, 2006

When I use Internet Explorers' Conditional Comments to serve rules only for IE5, IE 6 or even IE7, I use html body to increase the specifity to make sure that ito make sure it is not overriden by a higher specifity.

An example )in my IE CC:

html body div#myContainer
{
// my CSS rules here for IE WIN
}

In my general stylesheet I do:
div#myContainer
{
// CSS rules here
}

Dustin Diaz said on August 24, 2006

Specawicificimicity is gweat!

Ash Haque said on August 26, 2006

Great post, I never really understood the idea fully before :)

bart said on September 06, 2006

You can easily find out which rules are overriding others with the DOM Inspector > CSS Style Rules or Web Developer extension's View Style Information. Makes it a snap to troubleshoot specificity and cascade issues.

Ryan Wilke said on September 06, 2006

Hey Jonathon, thanks for a great article. I didn't notice how much I needed to read this until a few days later. Great work. I love how you got into the meat of the article right away. Thanks again.

Jeremy said on December 06, 2006

I'm having issues with my website here. A bit of background info: I'm just revamping/coming up with a new design. The last one I did over a year ago, so I'm trying to familiarize myself with CSS again.

Anyway...I think my main issue deals with specificity-but am not sure. If you just copy the link above WITHOUT the /newindex.htm, you'll see my .css file and the two pictures I'm trying to use.

Use IE to view it, please. I'll work it out in Mozilla later. What I'm trying to do here is to put the Nighthead.png file at the top (for the banner) and the "Welcome" in the HTML code is supposed to sit at the bottom left of that picture. Then, the "header" (the section with my picture in it) is supposed to house the Nightbody.png. Neither picture wants to go in its spot. If someone has time, can you kindly let me know if it is a specificity issue?

I'm clueless. Thanks.

Paul Decowski said on July 27, 2007

Jonathan,

On 23 August 2006 you wrote:

(…) (see my stylesheet) (…)

The link points to a non existing file and it also seems there is a problem with custom 404 page.

Just thought you would like to know and I’d also like to see your stylesheet ;).

Best regards,
Paul

Jonathan Snook said on July 27, 2007

@Paul: I've updated the link to point to the CSS file I was working with at the time. You can also see the CSS for the design that came after that (v7), and the one I'm using currently (v8). I didn't use indentation in the current version, although I still do on client projects.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.