How to use CSS specificity

If you plan to use CSS on a regular basis you need to develop an understanding of what specificity is and how it is applied.

Other than floats and positions, specificity may be one of the hardest things to get used to, let alone master. The selectors you use in your CSS all have different weights and those are controlled by specificity. That’s why sometimes, when you apply a rule to an element, it isn’t reflected in your design.

If you’ve ever relied on the dreaded !important keyword to hack your CSS, then this article is for you.

 

How a browser reads CSS

To get your foundations solid, you need know how the browser actually reads CSS and how rules are overridden.

Firstly the browser will read a stylesheet from top to bottom meaning that with this code:

/*Line 10*/
ul li a {
 color: red;
}

/*Line 90*/
ul li a {
 color: blue;
}

The rule you specified at line 10 will get overridden and that anchor tag will be blue because the browser will consider rules further down your CSS to hold a greater priority.

This also works with the actual order you import your css files , for example:

<link href='css/style.css' rel='stylesheet'>
<link href='css/custom.css' rel='stylesheet'>

Since you placed the custom.css after the the style.css anything you write in the style.css (discounting for now, the weight of selectors ) will get overridden and substituted for what is in the custom.css, this technique is often used by theme creators to give the user some room to add their own styles without changing the main file. (Note however that custom.css doesn’t replace style.css entirely, only those rules that are specifically overridden will be replaced.)

 

Specificity

Everything above only applies if you are using the same weight on every selector. If you’re specifying IDs, classes or stacking elements then you’re giving them weight, and that is specificity.

There are four categories that define the specificity level of a selector: inline styles (these ones are sometimes used by javascript), ID’s, Classes and elements. How to measure specificity? Specificity is measured in points, with the highest points value being applied.

  • ID’s are worth a 100 points.
  • Classes are worth 10 points.
  • Elements are worth 1 point.

Knowing this, if you use a selector like so:

#content .sidebar .module li a

Its total weight is 122 points ( 100 + 10 + 10 + 1 +1 ), which is an ID, two classes and two elements.

Things to remember

  • ID’s have way too much weight compared to classes and elements so you should limit the use of ID’s in your stylesheets to the bare minimum.
  • In cases where the selectors have the same weight the order they appear is reverted to, the latter being the higher priority.
  • Styles embedded in your HTML trump styles in stylesheets, because they are closer to the element.
  • The only way to override inline styles is to use the !important statement.
  • Pseudo classes and attributes have the same weight as normal classes.
  • Pseudo elements also have the same weight as a normal element.
  • The universal selector (*) holds no weight.

 

Examples

ul li a {
 color: red;
}

This selector will hold a weight of 3 , which means that just by adding a class somewhere else, you can override it.

.content #sidebar {
 width: 30%;
}

This selector has a weight of 110 points mainly because of the ID that adds 100 points of the 110 total.

.post p:first-letter {
 font-size: 16px;
}

This selector has a weight of 12 points ,since the pseudo-element :first-letter only weighs 1 point and so does the p tag.

p {
font-family: Helvetica, arial, sans-serif;
}

This selector only weighs 1 point , this type of selector should be used at the top of the page when you marking the basic styles that later on may be overridden for specific areas.

Always bear in mind that to override an ID selector you have to write 256 classes for the same element , like so:

#title {
 font-weight: bold;
}

.home .page .content .main .posts .post .post-content .headline-area .wrapper /* ... etc. ... */ .title {
  font-weight: normal;
}

Only this way will the second selector beat the one using the ID.

 

Conclusion

Specificity isn’t a flashy aspect of CSS, but in my opinion it’s the area most overlooked. Getting your specificity right not only helps you avoid bugs, but it will speed up both your development and your final site.

Do you overuse IDs when writing CSS? Do you ever fall back on !important? Let us know in the comments.

Featured image/thumbnail, precision image via Shutterstock.

0 shares
  • Soumya

    The part about using 10 classes to override an ID selector is very, very wrong. That’s not how it works.

    http://meyerweb.com/eric/css/link-specificity.html: “This implies a base-ten arithmetic. However, specificity calculations do NOT use base ten, a fact at which the specification hints but doesn’t come right out and say in big bold letters. If you chain fifteen simple selectors together, they still have a lower specificity than a simple class selector.”

    • Inga

      I think the link here http://css-tricks.com/specifics-on-css-specificity/ explains specificity most distinctly.

    • Sara Vieira

      Hello ,
      What you were talking about was for elements , you can actually override an id with class but it takes 256.
      http://codepen.io/chriscoyier/pen/lzjqh
      I’ve updated the article.

      • http://bittersmann.de/ Gunnar Bittersmann

        No, you cannot override an ID selector with even millions of class selectors. The example you’ve linked to demonstrates this: The element is blue, not red. Which means the ID selector still has higher specifity.

        Your article still got it wrong. I can’t see any changes from 10 to 256 anyway. But any finite number would be incorrect.

      • Vitzkrieg

        On Windows 7 it works in IE9/10 and Maxthon 3. Doesn’t work in Chrome or Opera and Firefox just hangs and had errors (from the site, not the pen code). So it looks like each browser has it’s own points algorithm.

      • http://bittersmann.de/ Gunnar Bittersmann

        Thanks for telling. I wasn’t aware of this IE bug.

        The CSS spec is a little vague at levels 2 http://www.w3.org/TR/CSS21/cascade.html#specificity and 3 http://www.w3.org/TR/css3-selectors/#specificity “Concatenating the three [four] numbers a-b-c[-d] (in a number system with a large base) gives the specificity.”

        Microsoft have taken this literally and decided 256 was “large”.

        What the spec should have said is “in a number system with an infinite base”.

        The current editor’s draft of the level 4 spec http://dev.w3.org/csswg/selectors4/#specificity drops this number system part and says: “Specificities are compared by comparing the three components in order: the specificity with a larger A value is more specific; if the two A values are tied, then the specificity with a larger B value is more specific; if the two B values are also tied, then the specificity with a larger c value is more specific; if all the values are tied, the two specifities are equal.”

        And continues: “Due to storage limitations, implementations may have limitations on the size of A, B, or c. If so, values higher than the limit must be clamped to that limit, and not overflow.”

        Not overflow. That’s what IE got wrong.

      • Zoltan Hawryluk

        @Gunnar: It looks like it is not just IE that does this. The latest Firefox (v. 21) does as well as the version of Safari I am using (5.1.9, which is the latest production version for OS 10.6).

      • Zoltan Hawryluk

        Also confirmed it behaves like this in Safari 6.0.5. Interestingly, that means only Chrome and Opera behave correctly.

  • Evert

    The line “The only way to override inline styles is to use the !important statement.” while correct should read:

    “The only way to override inline styles with the highest possible specificity is to use the !important statement.”
    I often override inline styles by using a selector that has a greater specificity.

  • 1076

    I’ve found that’s an especially good habit to get in to when writing javascript apps or plugins. That way you won’t be taking up ids that the person using your plugin has already used (even if your naming structure makes that unlikely).

  • http://twitter.com/LewisCowles1 Lewis Cowles

    sorry, but this no id movement is a load of hooey id’s have lots of features that are useful and while classes are great for re-usability, id’s enforce having one object on the page with the same id. While it is true not to use id’s unless necessary they can be a powerful tool for the web designer that uses them sparingly and in the right context and situation!

    • Sara Vieira

      That’s exactly what I am saying , you should know when to use them and there are situations in which you need and ID in your stylesheet because a class wouldn’t work and that’s fine . All I am saying is that you should try to avoid it in your stylesheet , no on your HTML because performance wise because id’s work a lot better with jQuery and Javascript in general than classes.

      • http://twitter.com/LewisCowles1 Lewis Cowles

        I use id’s in my css as well, I just do not use them exclusively, nor would I exclusively use classes. If I used anything exclusively it would be because the alternatives had been deprecated. I sincerely hope that never happens because one selector is name based singular, and the other is supposed to be for lists, so there should be a performance gain to using id’s appropriately, and not just for JS

  • http://www.blackbookoperations.com/ Black Book Operations

    That’s one of the better reasons not to use the hashtag indeed ;) (just as well as using “jQuery” as a selector in well… jQuery as opposed to the “$” sign (unless u declare all dollar signs as being “jQuery”) well, I could’ve explained myself better here, but I think u’ll catch my drift ;)

  • Vignesh RajaRajan

    I came to know about this now only.. Thanks for this wonderful article.