Menu

How CSS Specificity Works


Knowing how CSS specificity works is a fundamental skill.

It will give you a deeper understanding of how CSS property values are resolved when two or more style rules match the same set of HTML elements.

Troubleshooting your CSS is easier when you can determine the specificity values of your selectors. For example, when there's a style rule that isn't working as intended, there's probably another style rule somewhere that's overriding it. You'll be able to quickly correct these issues by learning about CSS specificity.

How It Works

If multiple CSS selectors are targeting the same set of HTML elements, and if the CSS selectors are trying to assign the same property/properties to the HTML elements, the selector with the highest specificity value will "win".

In other words, the most specific selector gets to assign its property values to the HTML elements.

It's easier to explain with an example.

Let's say this is our HTML:

<div class="container">
  <div id="main">
    <p>
      <a href="#">Link</a>
    </p>
  </div>
</div>

We want to assign a color to the <a> tag above.

There are many ways to target that <a> tag using CSS selectors. Below are five style rules that can get the job done:

#main a {
  color: green;
}
p a {
  color: yellow;
}
.container #main a {
  color: pink;
}
div #main p a {
  color: orange;
}
a {
  color: red;
}

Since all five style rules are trying to assign a color property value to the <a> tag, the browser gets confused: Should the link be green, yellow, pink, orange or red?

The browser needs a way to negotiate which color it should give to our <a> tag.

The way the browser makes the decision is by first calculating each selectors' specificity value. Then it checks which selector has the highest value. That's the winner. That will be the selector who gets the honor of setting the color property value of our <a> tag.

Here are our five style rules again, in order from most specific to least specific.

SelectorSpecificityValue
.container #main a111
div #main p a103
#main a101
p a2
a1

So our <a> tag is pink.

If we remove .container #main a from our stylesheet, our link will become orange because the next most specific selector is div #main p a.

How did I know the specificity values for each selector? I calculated them.

Figuring Out Specificity Values

Understanding CSS selector specificity rules will all seem complicated at first.

For example, when I was still learning about CSS specificity, I had to write down my calculations on a piece of paper. Just like back in school when solving math problems.

It will take time and practice before this all becomes second nature.

OK, so let's actually go over how to calculate a selector's specificity value.

The method I'll show you for determining specificity values is from W3C CSS Selectors Level 3 specifications.

The Basics

The specificity value is:

abc

Where:

 Total number of...

a

  • ID selectors

b

  • Class selectors
  • Attribute selectors
  • Pseudo-classes

c

  • Type selectors
  • Pseudo-elements

Visual illustration of CSS selector specificity groupings.

Example

#header .navbar li a:visited
abc
122
Specificity value: 122

We'll go through more examples in just a bit.

Selector Types

Before you can calculate specificity values, you'll need to be familiar with the types of CSS selectors:

TypeDescriptionExamples

ID selectors

They begin with a hash.

#id

#container

#main

#sidebar

Class selectors

They begin with a period.

.class

.navbar

.logo

.primary-color

Attribute selectors

They're in brackets.

[attribute]

[type="text"]

[rel="nofollow"]

[class^="cont"]

Pseudo-classes

They begin with a colon.

:pseudo-class

:visited

:hover

:active

Type selectors

They're the name of standard HTML elements.

div

ul

a

Pseudo-elements

They begin with two colons.

::pseudo-elements

::before

::after

::first-line

Special Rules

My Technique for Calculating Specificity Values

I'm terrible with numbers. So I had a tough time calculating specificity values in my head at first.

So whenever I needed to figure out a specificity value, I'd sketch out a sort of grid matrix on a piece of paper. Then I'd count each selector type and log them in the appropriate column. Figuring out the specificity value was a piece of cake after that. It looks like this:

CSS specificity grid

To double-check my work, I'll first count the number of selectors. Then I'll add up a + b + c. The total number of selectors must be equal to the sum of a + b + c.

Otherwise, something went wrong.

For example, if the CSS specificity value is 122, then there should be five selectors.

abc
122
Specificity value: 122
Double-check: 1 + 2 + 2 = 5 selectors

This technique is slow. And there are tons of tools out there that can do this work for us.

But I figured that if I wanted to understand the concept, I needed to do it slowly and manually. This allowed me to fully absorb the idea behind CSS specificity.

CSS Specificity Examples

Let's go through some examples.

Example 1

div#container #main ul li

abc
203
Specificity value: 203
Double-check: 2 + 0 + 3 = 5 selectors

Example 2

table tbody tr.even td.odd

abc
024
Specificity value: 24
Double-check: 0 + 2 + 4 = 6 selectors

Example 3

.navbar ul.menu li#first a:not(:visited)

abc
133
Specificity value: 133
Double-check: 1 + 3 + 3 = 7 selectors

Example 4

.footer #menu li#sponsor a[rel=nofollow]::before {
  content: "sponsored link: ";
}

abc
223
Specificity value: 223
Double-check: 2 + 2 + 3 = 7 selectors

Quiz

You're not getting off that easy!

Here's a quick challenge for you. See how many questions you can get right.

1. What are the values of a, b and c in the following CSS selector?

.wrapper h1 a

See the answer

Answer

abc
012

2. What's the specificity value of the following CSS selector?

.nav ul#menu li a

See the answer

Answer

abc
113
Specificity value: 113

3. What's the specificity value of the CSS selector below?

.footer span a:not(#about-page)

See the answer

Answer

abc
112
Specificity value: 112

4. Which letter does the universal selector get counted in? a, b or c?

See the answer

Answer

None

The universal selector should be ignored when calculating CSS specificity.

In the following example, <h1> tags will be green.

* { color: red; }
h1 { color: green; }

5. What's the font size of the <p> elements in the following example?

HTML

<body>
  <div class="main">
    <div class="intro">
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
      <p>Paragraph 3</p>
    </div>
  </div>
</body>

CSS

body p { font-size: 16px; }
div.intro p { font-size: 24px; }
div.main p { font-size: 20px; }

See the answer

Answer

20px

In this case, the last two selectors have the same specificity value.

div.intro p
abc
012
Specificity value: 12
div.main p
abc
012
Specificity value: 12

When there's a tie, the selector farthest down the stylesheet wins.

6. What's the color of the <h1> element in the following example?

HTML

<div class="container">
  <div class="post">
    <h1>My Blog Post Title</h1>
    <p>This is my blog post.</p>
  </div>
</div>

CSS

.container .post h1 {
  color: yellow;
}
.post h1 {
  color: red;
}
h1 {
  color: blue;
}
div.container div.post h1[class="heading"]  {
  color: green;
}

See the answer

Answer

Yellow

If you answered green -- you should know this was a trick question. (Sorry!)

When you do the math, the selector with the highest specificity value is the last selector: div.container div.post h1[class="heading"].

But... the h1 element doesn't have a class attribute of heading. So the last selector won't be able to select the h1 element in our example.

In the comments, tell us how you fared in quiz.

References

Updates

Related Content

Jacob Gube is the founder of Six Revisions. He’s a front-end developer. Connect with him on Twitter and Facebook.

This was published on May 27, 2015

22 Comments

A very nice, and well explained tutorial on css specificity! Loved the animated .gifs that you used to explain it. :)

    Jacob Gube May 27 2015

    Thank you for your kind words!

    I’m glad you loved the animated .gifs/visual aids . I hope they help visual learners better understand CSS specificity. They took quite a lot of time and effort to conceptualize and create.

EJ Frias May 28 2015

Another great article Jacob! Very detailed explanations, I’ve learned something new again. But I must admit, you got me on the last question of the test! :D

    Jacob Gube May 28 2015

    Thank you EJ! (And, again, sorry!)

Good article, clearly explains how this works.

The animated gifs really did help to make it very clear how the rules worked and the quiz at the end allowed me to check I had understood.

    Jacob Gube May 28 2015

    Nice! Exactly what I was going for! Thanks Nathan!

Alexandre Rousseau May 28 2015

Thanks for this.

luis betancourt May 28 2015

Great article! i knew you could be specific in order to override css styles but calculating the specificity is something that was a mystery to me.

    Jacob Gube May 28 2015

    I hope this article will help demystify CSS specificity for you luis!

Very informative article Jacob.

Give me a glimpse of my styles which weren’t applying due to some ‘x’ styles even though they were lying ahead of ‘x’ in css sheet.

Thanks a ton!!!

    Jacob Gube May 29 2015

    Exactly! I’m glad you see the value of knowing how CSS specificity works Ravi!

    Question 5 in the quiz highlights the importance of CSS specificity. Many developers who are still starting out will think the div.intro p style rule will be applied because it’s nested inside div.main. But if you calculate CSS specificity, they’re actually equally specific, and so the style rule further down the stylesheet will win.

Kerry Webster Jun 02 2015

Bravo!!!

SelenIT Jun 04 2015

It seems that this article is not very accurate about :not() selector. It says that :not() counts as a single pseudo-class, no matter what is inside. However, the spec says the opposite — :not() itself is not counted at all, but selector inside it is counted as usual. Here is the proof: http://jsfiddle.net/zdmvgspw/

This difference will become more significant with CSS Selectors 4, where complex selectors are allowed within :not().

    Jacob Gube Jun 04 2015

    Give me a moment to review what you’ve just said. Will be back with my response.

    Jacob Gube Jun 04 2015

    You are correct SelenIT. I made a major error in this article with regards to the negation pseudo-class specificity calculation. Thank you for pointing this out. You even went through the trouble of creating a test case on JSFiddle.

    To make sure, I tried to see if I would get the same results as you with my own test case. My test case is additional proof that what you said is correct: http://jsfiddle.net/qj2bxpd4/

    I will be correcting this article within the next few hours.

    Here is what the specification says about :not() selector’s specificity calculation:

    Selectors inside the negation pseudo-class are counted like any other, but the negation itself does not count as a pseudo-class.
    9. Calculating a selector’s specificity

    What I have said in this article is the opposite of what the specification says.

    Can I email you via the email address you used when you left your comment? I want to send you an Amazon gift card as a small token of my appreciation for reviewing and helping me correct this article. Thank you so much SelenIT.

    Jacob Gube Jun 04 2015

    I have updated the article. Thank you again SelenIT.

Stefanie Jun 10 2015

Thank you for this tutorial! Now I understand the (sometimes) strange behaviour of my styles. Your tutorial was exactly what I was looking for (nice written and understandable). Great job!

Luis Alfredo Jun 26 2015

I would like to see an article about the specificity when used:

.element > .element
vs
.element + .element
vs
.element .element

Nice, very easy to understand.

I think the answer here is wrong:
.footer span a:not(#about-page)
It should be 112 (as in your table), but you wrote 122.
Great article!

    Jacob Gube Nov 20 2015

    You’re absolutely correct Vest. I indeed made an error. I’ve corrected the post. Thank you so much for bringing the issue to my attention Vest.

This comment section is closed. Please contact us if you have important new information about this post.

Partners