CSS Specificity Explained

Abdulqudus Abubakre - Jul 23 '20 - - Dev Community

In this article, I'll be explaining what CSS spe-ci-fi-ci-ty is and how it works in very simple terms.

Remember when you were watching that tutorial on CSS and you were told styles are applied from top to bottom, and that the styles that appear below would overwrite the one at the top....well that's not the full story.

CSS Specificity

CSS Specificity is the set of the rules applied to CSS selectors in order to determine which style is applied to an element. With proper understanding, you will understand why a style is not being applied to the element or why a particular style is applied even if there's a declaration below that overwrites it.

Let's look at this example:

.btn {
  color: #fff;
  background-color: blue;
}

.btn {
  color: #fff;
  background-color: red;
}
Enter fullscreen mode Exit fullscreen mode

If we were to check this in our browser, our button would have a background color of red and a text color of white. That is fine, considering the styles that appear after would overwrite the one before. But what if we had something like this?

.btn.bg {
  color: #fff;
  background-color: red;
}

.btn {
  color: #fff;
  background-color: blue;
}
Enter fullscreen mode Exit fullscreen mode

You'd expect the button to have a blue background, but in this case, the button would have a background color of red.

The reason for this behavior is, you guessed right.... CSS Specificity

How does it work?

CSS selectors have weights applied to them, and the more the weights, the higher the priority.

Image showing specificity weight

Styles
This refers to the inline styling applied to an element. e.g

<button style="background-color: red">Submit</button>
Enter fullscreen mode Exit fullscreen mode

The specificity for this is (1, 0, 0, 0), and it has the highest weight. To override this, you would need to use the !important flag in your CSS, but that's not really advisable.

ID
Using an id selector would give a specificity of (0, 1, 0, 0).

#btn {
  background-color: red;
}
Enter fullscreen mode Exit fullscreen mode

ID's have a higher priority compared to classes and tag names.

Classes, pseudo-classes and attributes
Class selectors like:

.btn {
  background-color: red;
}
Enter fullscreen mode Exit fullscreen mode

Pseudo-classes like

.btn:hover {
  background-color: red;
}
Enter fullscreen mode Exit fullscreen mode

and attribute selectors like

.btn[type=submit]{
  background-color: red;
}
Enter fullscreen mode Exit fullscreen mode

all have a specificity of (0, 0, 1, 0)

Tag Names
Selecting a element using it's tag name has the least specificity of (0, 0, 0, 1). Here's an example of tag name selectors.

button {
  background-color: red;
}
Enter fullscreen mode Exit fullscreen mode

Examples

1 - Assuming we have the following html

<ul class="nav">
  <li class="nav-item">Home</li>
  <li class="nav-item">About</li>
  <li class="nav-item">Contact</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

And the CSS:

li {
  color: red;
}

ul > li {
  color: blue;
}

.nav-item {
  color: green;
}
Enter fullscreen mode Exit fullscreen mode
  • The specificity of the first selector would (0, 0, 0, 1).
  • The specificity of the second selector would be (0, 0, 0, 2), because we have two element selectors.
  • The specificity of the last selector would be (0, 0, 1, 0). When you view this in your browser, the elements should have a green color. In this case, it does not matter which one comes first, the one with the highest specificity wins. Let's do another one😉

2 - Given this html structure

<ul id="nav">
  <li class="nav-item">Home</li>
  <li class="nav-item">About</li>
  <li class="nav-item">Contact</li>
</ul>
Enter fullscreen mode Exit fullscreen mode
#nav > .nav-item:hover {
  color: pink;
}

#nav > li:hover {
  color: brown;
}

li.nav-item:hover {
  color: orange;
}
Enter fullscreen mode Exit fullscreen mode
  • The first selector has a specificity of (0, 1, 2, 0)
  • The second selector has a specificity of (0, 1, 1, 1)
  • The third selector has a specificity of (0, 0, 2, 1) In this case, the color of the list item on hover would be pink, since the #nav > .nav-item:hover selector has the highest specificity.

3 - Take a look at this complex selector.

#container main .card img:hover {
  transform: scale(1.1);
}
Enter fullscreen mode Exit fullscreen mode

The specificity for this would be (0, 1, 2, 2). Let's break this down.

Selector Specificity
#container (0, 1, 0, 0)
main (0, 0, 0, 1)
.card (0, 0, 1, 0)
img (0, 0, 0, 1)
:hover (0, 0, 1, 0)
Total (0, 1, 2, 2)

And that's it. With proper understanding of how CSS specificity works, you'll easily able to debug your CSS. Some code editors like VSCode gives you hint about the specificity of the selector. All you need to do is hover on the selector. Here's how it would look in my VSCode:
VSCode hint for CSS specificity

Useful Tips

  • Avoid using ID's and inline styling as much as possible. To override these, you might have to use another ID, an inline style or the !important flag.
  • If two CSS selectors have the same specificity, the last one is considered
  • Weights are considered before the number, so a specificity of (0, 1, 0, 0) has a higher precedence to (0, 0, 2, 2)
. . . . . . . . . . . . . . . . . .