Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade

Have you ever run into the situation where you’re trying to apply a css style to an element, but it won’t take? Your page it seems to be ignoring your css, but you can’t figure out why. Maybe you found yourself using !important or adding an inline style as a last resort. There’s a good chance the problem you encountered was one of css precedence.

A better understanding of which css styles take precedence can lead to less frustration with css, cleaner code, and more organized css so let’s look at three things that control which css rule applies to a given html element:

  • Specificity Calculations
  • Inheritance
  • The Cascade

Learning these rules will take you to the next level in your css development.

Specificity Calculations

Imagine your html contains a paragraph with a class of “bio” applied to it. You also have the following two css rules:

{code type=css}
p {font-size: 12px}
p.bio {font-size: 14px}
{/code}

Would you expect the text in your paragraph to be 12px or 14px? You can probably guess in this case it will be 14px. The second line of css (p.bio) is more specific than the first when it comes to your class=”bio” paragraph. However, sometimes the specificity isn’t so easy to see.

For example consider the following html and css

{code type=html}

{/code}

{code type=css}
div p.bio {font-size: 14px}
#sidebar p {font-size: 12px}
{/code}

The first line of css might seem more specific at first glance, but it’s actually the second line above that would be more specific to the font-size of your paragraph. Why is that?

To answer the question we need to consider the rules of specificity.

Specificity is calculated by counting various components of your css and expressing them in a form (a,b,c,d). This will be clearer with an example, but first the components.

  • Element, Pseudo Element: d = 1 – (0,0,0,1)
  • Class, Pseudo class, Attribute: c = 1 – (0,0,1,0)
  • Id: b = 1 – (0,1,0,0)
  • Inline Style: a = 1 – (1,0,0,0)

An id is more specific than a class is more specific than an element.

You calculate specificity by counting each of the above and adding 1 to either a,b,c, or d. It’s also important to note that 0,0,1,0 is more specific than 0,0,0,15. Let’s look at some examples to make the calculation clearer.

  • p: 1 element – (0,0,0,1)
  • div: 1 element – (0,0,0,1)
  • #sidebar: 1 id – (0,1,0,0)
  • div#sidebar: 1 element, 1 id – (0,1,0,1)
  • div#sidebar p: 2 elements, 1 id – (0,1,0,2)
  • div#sidebar p.bio: 2 elements, 1 class, 1 id – (0,1,1,2)

Let’s look again at the example above

{code type=css}
div p.bio {font-size: 14px} – (0,0,1,2)
#sidebar p {font-size: 12px} – (0,1,0,1)
{/code}

The second has the higher specificity and thus takes precedence.

One last point before we move on. Importance trumps specificity, When you mark a css property with !important you’re overriding specificity rules and so

{code type=css}
div p.bio {font-size: 14px !important}
#sidebar p {font-size: 12px}
{/code}

means the first line of css above takes precedence instead of the second. !important is still mostly a hack around the basic rules and is something you should never need if you understand how the rules work.

Inheritance

The idea behind inheritance is relatively easy to understand. Elements inherit styles from their parent container. If you set the body tag to use color: red then the text for all elements inside the body will also be red unless otherwise specified.

Not all css properties are inherited, though. For example margins and paddings are non-inherited properties. If you set a margin or padding on a div, the paragraphs inside that div do not inherit the margin and padding you set on the div. The paragraph will use the default browser margin and padding until you declare otherwise.

You can explicitly set a property to inherit styles from it’s parent container, though. For example you could declare

{code type=css}
p {margin: inherit; padding: inherit}
{/code}

and your paragraph would then inherit both from it’s containing element.

The Cascade

At the highest level the cascade is what controls all css precedence and works as follows.

  1. Find all css declarations that apply to the element and property in question.
  2. Sort by origin and weight. Origin refers to the source of the declaration (author styles, user styles, browser defaults) and weight refers to the importance of the declaration. (author has more weight than user which has more weight than default. !importance has more weight than normal declarations)
  3. Calculate specificity
  4. If two rules are equal in all of the above, the one declared last wins. CSS embedded in the html always come after external stylesheets regardless of the order in the html

#3 above is likely the one you’ll need to pay attention to most. With #2 just understand that your styles will override how a user sets their browser unless they set their rules to be important.

Also realize that your styles will override the browser defaults, but those defaults do exist and is often what leads to cross browser issues. Using a reset file like Eric Meyer’s CSS Reset or Yahoo’s YUI Reset CSS helps take the default styles out of the equation.

Summary

Hopefully the above helps sort out some of your css precedence issues. Most of the time if you have a conflict in styles the issue will come down to specificity. At times when you haven’t declared some css, but an element is behaving in a way you don’t expect it’s likely that element has inherited some css from a parent container or a default style of the browser.

A general rule of thumb when declaring your css is to declare properties with the least specificity needed to style your elements. Use #sidebar instead of div#sidebar for example. I admit to breaking this general rule far more than I should, but by using the least specificity needed it will make it easier for you to override a style by declaring a style more specific.

If you use the most specificity you may run into problems later and find yourself having to add unnecessary html in order to be able to add more specificity or you may find yourself falling back on using !important or declaring inline styles. Start with the least specificity and add more only as needed.

« »

Download a free sample from my book, Design Fundamentals.

101 comments

  1. This helps answer a few things I have come across when doing CSS. I can usually work my way through them, but its good to understand the reason thing happen.

  2. Glad I could help Bryan. The specificity rules are out there, but I think quite a few people miss them. I know at times I’ve added some css and couldn’t figure out why it didn’t change how things displayed. Usually the answer is making the new rule more specific.

  3. The information that you have shared in this post is really valuable and the description is also easy to understand. It is really great.

    • Hopefully it can help a few people past the beginner stage too. This stuff wasn’t always clear to me when I first started learning css and writing the post actually cleared up a few things for me.

    • It can be easy to ignore and work around, but if you do pay attention to it you can end up writing leaner code and you’ll likely have a few less headaches here and there wondering why one of your styles won’t take.

  4. Well, i used to change things and see if they work. I had this problem and i didn’t know that was the case. I kept trying and it didn’t worked until i specified the highest ID from the HTML structure.

    • I used to do that too. Sometimes the specificity of things can be confusing or difficult to see so you add more and more higher level selectors.

      However the more you think about specificity as you’re writing your css, the more you won’t have to work your way back up the stack and the leaner you can make your code.

  5. Superb article; it’s helped me immensely to understand how CSS rules get assigned precedence, which has been bugging me a lot recently.

    One small question: in the section on The Cascade, which source gets higher precedence? In the article, you said author > user > user agent. From my reading (albeit novice) of the w3school spec, it seemed to me that user stylesheets get the final say over author specs. Am I having reading difficulty? (It’s pretty likely..)

    • Thanks Andy.

      It could very well have been me misreading things. From my understanding the author stylesheet would take precedence unless the user has given their own stylesheet extra importance.

      I opened up Firefox’s preferences. On the content tab you set the fonts. If you click the advanced button, there’s a checkbox to allow pages to choose their own fonts, instead of the selections set. I’m pretty sure that’s checked by default and so the author style ends up taking precedence.

      If I uncheck the box then my font choices were displayed. I think unchecking the box is equivalent to setting !important on the user stylesheet which would then give the user styles more weight than the author styles.

      I’m pretty sure that’s how it works in all browsers, but again it could be me misreading things. I think I had to read over the section at w3.org a few times myself. 🙂

    • Glad I could help Bradford. Usually when you hit those scratching your head moments about why some css value isn’t taking hold, it’s almost always an issue with the precedence.

  6. I’ve been wrestling a mongrel python for months and always thought CSS was a joke, this has really enlightened me. why couldn’t someone have explained this to me earlier. probably because i may have stop reading after the word specificity.

    thank you very much!

    • Yeah the word specificity is one that doesn’t exactly make you want to read further. Not the most inviting word is it?

      Glad the post could help. It took me awhile to understand how this worked when I was first learning too so don’t feel bad if you were struggling with it.

  7. Thank you so much for this post. When I read the introductory paragraph I thought to myself “This has happened to me EVERY time I use CSS” and this article really clears up the confusion.

    • Glad I could help clear things up. Specificity took me a little while to get as well. I learned it through one of Eric Meyer’s books and I remember reading and rereading the section again and again to make things clear.

      The general concept was easy enough, but there were enough details to keep throwing me off.

  8. Great article and good job!

    You have explain this topic clearly that you have removed a great deal of confusion from my head. Now it seems so simple I’m more confident debugging other people’s stylesheets.

    Thanks!

    • Thanks alds. I’m glad I could help, Precedence doesn’t get talked about as much as it should and I think it’s something that confuses a lot of people. I know it too me a little while to figure it out.

  9. Great article!! Clear and SUCCINCT. I knew this existed but had no idea what the rules were.

    They need you at Adobe. You could certainly clear some things up over there!

  10. Hi Steven, thanks for the article but I had a question:

    p {width:200px;}
    #a {background-color:yellow;width:100px}

    abcde fghij klmno pqrst uvwxy

    In the above example, whenever I open it in a browser, the width is 200px (which is the paragraph’s) even though I set the div to 100px. Could you please explain why the p is getting the precedence? Thanks

    • Sorry it too so long to reply Eric. Your html didn’t come through in the comment. Could you post it again or email it to me. If you want to place the code here you have to use the html entity for the angle brackets.

      I’m guessing the issue is that since the p is inside the div it’s forcing the div to be wider. That’s not really an issue of css precedence. Since you’re specifically setting the width on the paragraph it will be that width (200px) and overflow the div, even though the div is set to be smaller (100px)

      You could set the paragraph to use max-width instead of width

      p {max-width: 200px}

      Then it would never get wider than it’s parent container. Of course you don’t need to set the width at all in this case.

  11. Very nicely explained, has cleared up a few things for me.

    What always causes me issues is that its counter intuitive, in that styles declare further away from an element take precedence over ones declared closer. What lead me here today were these two styles:

    .mimic_adminAddObject > DIV SELECT
    { width: 150px; }
    .mimic_adminAddObjectSize SELECT
    { width: 70px; }
    In the structure:
    <div class=’mimic_adminAddObject>
    <select />
    <div class=’mimic_adminAddObjectSize’>
    <select />
    </div>
    </div>
    Crazily both were set as width 150, now at least I understand why, even though logically its wrong.

  12. Great post. (Some more discussion about in-line styling would be helpful too.) It inspired me to experiment a bit.
    I notice that the CSS settings based on html attributes override classes, so for instance “input:read-only” overrides “input.mycssclass”. Moreover, specifying the type of element overrides both class and attributes, so for instance “input[type=”text”].mycssclass” overrides both “input:read-only” and “input.mycssclass”.

    • Thanks Andy. Ideally you wouldn’t be using inline styles at all, 🙂 but if you are they’d take precedence since they’re closer to the html element.

      Interesting about the html attributes. When I wrote this post I wasn’t thinking at all about attributes or how they fit into all of this. Maybe I should do some experimenting myself and a little research and refresh this post or write a new one.

      Thanks for pointing it out.

  13. I read the spec and today your article. For all practical purposes, both docs say the same thing on specificity, except your article is MUCH easier to digest. Thank you for another great write-up. Very helpful.

  14. Very helpful article–well written, concise, comprehensive and clear. Thanks very much for the explanation of precedence.

  15. Thanks both for explaining this so clearly and for keeping the article alive all these years! You said at the beginning this will help take you to the next level. I wish I were so confident 😉 I have been enjoying putting Zurb’s Foundation to work on one of my web sites, but the design calls for the background to be black (versus white/off-white native to Foundation) so I came looking for a rule of precedence relating to “who wins” when two .css files are loaded. Because of your article I now know why some of my attempts to alter the background color of a class weren’t getting me anywhere! I’ll keep looking for the answer to the “who wins” question. But I appreciate knowing more about specificity.

  16. Actually, your article did answer my question! Foundation.css used a div.panel{} selector and I was trying to override with just .panel{} — so by being more specific (div.panel{}) my secondary .css file successfully overrode Foundation’s code. Thank you!

  17. Thanks very much for writing this. It just saved me tearing my hair out! It’s a good clear explanation of something I knew nothing about until about 30 minutes ago… and it explains why things haven’t behaved as I’ve expected them to in the past.

    • Glad I could help David. Yeah, this stuff confused me a lot when I was first learning css. I’d keep wondering why certain styles weren’t taking and yep, tearing my hair out.

      Once I understood what was going on I could see when things weren’t behaving like I expected it was usually a specificity issue.

  18. I always considered that it is determined based on which one is more specific, but this precedence rule came with thunderbolt.

    I was working with these.
    .p.class_name
    .class_name p

    I thought that the first one has higher precedence, but later found that they have same precedence!!

    • Glad I could help Sakib. All this precedence stuff confused me at first too. It’s important information to know though, since it’s often the issue when some css you apply doesn’t seem to take effect.

  19. Almost 4 years after the post – and people still find it very useful.

    Thanks alot for the clear and simple information!

    Great post!

  20. Does the stacking order of the actual CSS stylesheets matter as well? When you mention ‘source’ I thought that is what you meant, but it wasn’t. For example:

    styles.css
    custom.css
    main.css

    Say in each stylesheet, there is a default rule set for the list-style property of a list-item. Styles.css sets disc, custom.css sets an image and main.css sets none. All these styles sheets are linked on a webpage in the order above. What list-style would the page actually display?

    • If you have several css rules on the same selector then whichever comes last will be the one that gets used.

      In your example list-style would be none, since that value is in main.css, which comes last.

      That’s only if the selector is exactly the same. For example is main.css has

      li { list-style: none }

      and styles.css has

      li.class { list-style: disc }

      then a list item with a class of “class” will still get the disc.

      This isn’t only for different stylesheets either. If you have

      li { list-style: disc }
      li { list-style: none }

      in the same stylesheet then whichever comes last is still the one that applies.

  21. Information is very useful, Thanks, what if internal css style or external css sheet with same elements set, which will take more priority?

  22. Great post!
    Yet I got a question. I think “element style” is a better description for “inline style” in the post. Browers using element style refers to style defined in html tags, and Firefox call internal style sheet as inline style sheet, so I think “elment style” is more precise. What do you think of this, Steven?

    • I can see element style as the description, though it’s a little late, since they’ve been called inline styles since the beginning of CSS.

      Also if you think about it styles set in an external style sheet would still be element styles if they’re applied to an element instead of a class or id.

      Interesting thought, though.

  23. Brilliant! First google result for ‘css precedence’ and well deserved. The information was in my brain but not clearly enough to put into words. I wish someone had set this out for me 10 years ago. Thank you!

    • Thanks John. Everything I learned about CSS precedence comes from Eric Meyer’s book Cascading Style Sheets 2.0 Programmer’s Reference. It’s an old book so it’s probably not the best one to buy at this point, but I did find another book from Eric Meyer focused on specificity called Selectors, Specificity, and the Cascade that’s newer.

      Really any book by Eric about CSS is worth buying.

  24. This was a great article. Thank you so much for posting.

    One thing you didn’t mention here, (which I expected to find here); How the precedence of styles is based on their order in the stylesheet, not the order of the HTML.

    For example:

    The following code would produce a red div, whereas one might expect a green one.

    .style-b { background: green; }
    .style-a { background: red; }

    More here: http://plnkr.co/edit/JdGjLYlWthfTTOV2hBLf?p=preview

    • Thanks Alistair. Sorry it took me so long to reply. I thought I did mention the order in the CSS as well as the HTML. Maybe I need read my own article again. I thought I talked about order in general and that whichever styles come last apply, barring the specificity.

  25. This is an awesome post that is greatly under emphasized! Understanding this is one of the fundamental concepts of CASCADING style sheets and can save you timeless hours and/or needless amounts of code; nested divs are WAY too common practice and are poor work around for getting the page to render as desired. Leveraging this core structure greatly simplifies design structure and increases readability of code and site layout.

  26. Great post, Thanks 🙂

    I have on question:
    I declare my body with margin of 50px:

    body {
    margin: 50px;
    }

    I created a paragraph inside the body:

    I am a p

    When I open the inspector I find out that the P got 16 pixels in the margin bottom and top..Why?

    Thank you so much 🙂

    • A paragraph is a block level element and it comes with a default margin on top and bottom. The default is 1em, which is 16px, which is what you see. If you prefer a margin other than the default, you’ll have to set it.

      A lot of elements have default values. Here’s a table showing them.

      Hope that helps.

Leave a Reply

Your email address will not be published. Required fields are marked *