Specificity Point System in CSS

One might think of Specificity in CSS as a tool to better understand what's going on in the cascade.

CSS provides a formula for determining a style's specificity. This formula is ultimately the value that's assigned to the style blocks' selector - a tag selector, class selector, ID selector, pseudo selector and so on. Here's how the system works:

  • A tag selector is worth 1 point
  • A pseudo-element (e.g. :first-child) is treated like a tag and is worth 1 point
  • A class selector is worth 10 points
  • A pseudo-class (e.g. :link) is treated like a class and is worth 10 points
  • An attribute selector is worth 10 points
  • An ID selector is worth 100 points
  • An inline style is worth 1,000 points
  • The !important declaration is worth 10,000+ points

    /* adds 2 id's (#wrap and #main), 2 class's (.widget and :active), and 1 tag (a) giving a specificity of 221 */
    #wrap #main .widget a:active {
        margin-right: 10px;
    }


The math involved in calculating specificity is actually a bit more complicated, but this formula works in all but the weirdest cases. See the CSS 2.1 specification on specificity for the exact formula used. It's actually a little more like linux permissions once you look at it.

One particularly heavy handed approach for adding specificity is using the !important rule. This one is the silver bullet - using this declaration will override any other style declarations, even if they are inline. This should only be used in very rare cases and it should be understood that after applying a style with this declaration you'll no longer be able to override it except by adding more !important style selectors later in the cascade. It's a slippery slope and should be avoided if at all possible.

Now, let's be real, sometimes you literally just HAVE to use it for some reason or another. So, let's cover that case. You might use it when you have a matched set of elements/attributes that should use a certain set of styling no matter what. You also could be working off of someone else's hack job that you have no control over, either way - it's OK - it's ok. Working with !important is very similar to working with any other type of selector, it just has a super high specificity. It will override massive selectors and even inline styles. But you can override the !important rule.

The only way an !important value can be overridden is with another !important rule declared later in the cascade and otherwise with equal or greater specificity value.

Overall, the bigger the number the greater the specificity and that's how you can gauge how 'big' your selector needs to be in order to beat out whatever other styles you want to override.

Since descendant selectors are composed of several selectors - #content p, or h2 strong, for example - the math gets a bit more complicated. The specificity of a descendant selector is the total value of all of the selectors listed in the selector in question. So, have a look at the following:

    /* adds 1 id, 2 class's, and 3 tags giving a specificity of 123 */
    .en_US #sidebar-1 ul li:empty a {
        //styles
    }
 
    /* adds !important, 2 id's, 2 class's, and 3 tags giving a specificity of 10223 */
    .en_US #main #sidebar-1 ul li:empty a {
        color: red !important;
    }

At last it is possible for two styles with conflicting properties to have the same specificity. In this situation, the cascade comes back into play and the selector further down in the document (or loaded later) wins.