CSS Specificity

What happens when an element is targeted by multiple rules, with different selectors, that affect the same property?

For example, let's talk about this element:


<p class="dog-name">Roger</p>

We can have


.dog-name {
  color :yellow;
} 

and another rule that targets p, which sets the color to another value:


p {
  color :red;
} 

And another rule that targets p.dog-name . Which rule is going to take precedence over the others, and why?

Enter specificity. The more specific rule will win. If two or more rules have the same specificity, the one that appears last wins .

Sometimes what is more specific in practice is a bit confusing to beginners. I would say it's also confusing to experts that do not look at those rules that frequently, or simply overlook them.

How to calculate specificity

Specificity is calculated using a convention.

We have 4 slots, and each one of them starts at 0: 0 0 0 0 0. The slot at the left is the most important, and the rightmost one is the least important.

Like it works for numbers in the decimal system: 1 0 0 0.is higher than 0 1 0 0.

Slot 1

The first slot, the rightmost one, is the least important.

We increase this value when we have an element selector. An element is a tag name. If you have more than one element selector in the rule, you increment accordingly the value stored in this slot.

Example:


p {
}  /* 0 0 0 1 */

span {
}  /* 0 0 0 1 */

p span {
}  /* 0 0 0 2 */

p > span {
}  /* 0 0 0 2 */

div p > span {
}  /* 0 0 0 3 */

Slot 2

The second slot is incremented by 3 things:

  • class selectors
  • pseudo-class selectors
  • attribute selectors

Every time a rule meets one of those, we increment the value of the second column from the right.

Example:


.name {
}  /* 0 0 1 0 */

.users .name {
}  /* 0 0 2 0 */

[href$='.pdf'] {
}  /* 0 0 1 0 */

:hover {
}  /* 0 0 1 0 */

Of course slot 2 selectors can be combined with slot 1 selectors:


div .name {
}  /* 0 0 1 1 */

a[href$='.pdf'] {
}  /* 0 0 1 1 */

.pictures img:hover {
}  /* 0 0 2 1 */

One nice trick with classes is that you can repeat the same class and increase the specificity. For example:


.name {
}  /* 0 0 1 0 */

.name.name {
}  /* 0 0 2 0 */

.name.name.name {
}  /* 0 0 3 0 */

Slot 3

Slot 3 holds the most important thing that can affect your CSS specificity in a CSS file: the id.

Every element can have an idattribute assigned, and we can use that in our stylesheet to target the element.


#name {
}  /* 0 1 0 0 */

.user #name {
}  /* 0 1 1 0 */

.name. span {
}  /* 0 1 0 1 */

Slot 4

Slot 4 is affected by inline styles. Any inline style will have precedence over any rule defined in an external CSS file, or inside the styletag in the page header.

Example:


<p style="color: red">Test</p>/* 1 0 0 0 */

Even if any other rule in the CSS defines the color, this inline style rule is going to be applied. Except for one case - if !importantis used, which fills the slot 5.

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>

      .container p {
        color :green;
      } 

      .name {
        color :red;
      } 

      #name {
        color :purple;
      } 

      p {
        color :brown;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="container">
      <p>Test</p>
      <p class="name">Test</p>
      <p id="name">Test</p>
      <p style="color:yellow;">Test</p>
    </div>
  </body>
</html>

understanding specificity is very important because it will help you to control your CSS flow and to know how to style your website well.