Specifics on CSS Specificity

This article was originally published on August 11, 2008. I am updating it now to fix some inaccuracies in how this concept was presented.

I've never specifically covered this subject before. (rimshot!)

The best way to explain it is to start with an example of where specificity gets confusing and perhaps doesn't behave like you would expect. Then we'll take a closer look at how to calculate the actual specificity value to determine which selector takes precedence.

There is your trouble right there. Two different CSS selectors are telling that text what color and font-weight to be. There is only one statement for font-size, so clearly that one will take effect. These aren't "conflicts" per-say, but the browser does need to decide which one of these statements to honor. It does so by following a standard set of specificity rules.

I think this confuses some beginners because they haven't quite gotten this sorted out yet. They might think because the .favorite statement is "further down in the CSS" or because the class="favorite" is "closer to the actual text" in the HTML that will be the one that "wins".

In fact, the order of selectors in your CSS does play a role and the "further down" one does in fact win when the specificity values are exactly the same. For example:

.favorite {
color: red;
}
.favorite {
color: black;
}

The color will be black... but I digress.

The point here is you want to be as specific as it makes sense to be every chance you get. Even with the simple example presented above, it will become obvious to you eventually that simply using a class name to target that "favorite drink" isn't going to cut it, or won't be very safe even if it did work. It would have been smart to use this:

ul#summer-drinks li.favorite {
color: red;
font-weight: bold;
}

That is what I'm calling "being as specific as it makes sense to be". You could actually be way more specific and use something like this:

But that is over the top. It makes your CSS harder to read and yields no real benefits. Another way to juice up the specificity value for your ".favorite" class is to use the !important declaration.

.favorite {
color: red !important;
font-weight: bold !important;
}

I once heard it said that !important is like the Jedi mind trick for CSS. Indeed it is, and you can force your will over the styling of elements by using it. But !important imposes that will through drastically increasing the specificity of that particular selectors property.

The !important declaration can be easily misused if misunderstood. It is best used to keep your CSS cleaner, in examples where you know elements with a particular class selector should use a certain set of styling no matter what. Conversely, not used just as a quick crutch to override the styling of something instead of figuring out how the CSS was structured and working by the original author.

One of my classic examples is:

.last {
margin-right: 0 !important;
}

I often use that in situations where there are multiple floated blocks, for the last block on the right in a row. That ensures the last block doesn't have any right margin which would prevent it from butting snugly against the right edge of its parent. Each of those blocks probably has more specific CSS selectors that apply the right margin to begin with, but !important will break through that and take care of it with one simple/clean class.

Calculating CSS Specificity Value

Why is that our first attempt at changing the color and font-weight failed? As we learned, it was because simply using the class name by itself had a lower specificity value and was trumped by the other selector which targeted the unordered list with the ID value. The important words in that sentence were class and ID. CSS applies vastly different specificity weights to classes and IDs. In fact, an ID has infinitely more specificity value! That is, no amount of classes alone can outweigh an ID.

Let's take a look at how the numbers are actually calculated:

In otherwords:

If the element has inline styling, that automatically1 wins (1,0,0,0 points)

You can generally read the values as if they were just a number, like 1,0,0,0 is "1000", and so clearly wins over a specificity of 0,1,0,0 or "100". The commas are there to remind us that this isn't really a "base 10" system, in that you could technically have a specificity value of like 0,1,13,4 - and that "13" doesn't spill over like a base 10 system would.

Sample calculations

Update: The :not() sort-of-pseudo-class adds no specificity by itself, only what's inside the parens is added to specificity value.

Important Notes

The universal selector (*) has no specificity value (0,0,0,0)

Pseudo-elements (e.g. :first-line) get 0,0,0,1 unlike their psuedo-class brethren which get 0,0,1,0

The pseudo-class :not() adds no specificity by itself, only what's inside it's parentheses.

The !important value appended a CSS property value is an automatic win. It overrides even inline styles from the markup. The only way an !important value can be overridden is with another !important rule declared later in the CSS and with equal or great specificity value otherwise. You could think of it as adding 1,0,0,0,0 to the specificity value.

Related

Comments

Hello!
Thanks for this article! I’ve gotten into a real habit of using very specific styles recently. Also I really like how you layout your CSS file from looking at some of the screencasts you have! That has helped a lot and now my CSS files are so much easier to read.
Keep up the good work on the site!
ChaZ

I would also recommend checking out and test the CSS Specificity Calculator. Just paste in your CSS and it’ll calculate the specificity for you. It really comes in handy if you’re working on large CSS files (instead of multiple smaller ones).

The calculation is not based on “addition” of the values. The specificity calculation is instead based on the left most value being the highest. If two competing selectors have matching values for a given identification unit, then comparison continues towards the left next order until a larger value is found.

Pablo – CSS Variables are on their way. They’re available in the most recent builds of Webkit (Safari) but won’t be mainstream for quite a while yet.

If you split your styles up into typography and structure/layout it can make it a lot easier to change – however depending on the size of your stylesheet it can make things a bit harder to find – eg. if you’re looking for all styles of a particular element/selector you have to reference multiple locations instead of just the combined typo/structure one.

Jonathan is entirely correct, and the article is deeply misleading on that particular point. Specificity is not base-10. It’s not base-anything-familiar: in fact, specificity values have an infinite base. Really. So you don’t “add points together, at least not in the manner which just about anyone reading this article would assume.

I — for one — fell in love with your base-10 approximation that so cleverly lends itself to intuitive graphical examples. I often explain specificity to co-workers, but never have my words been as clear as when (this morning) I was armed with a printed copy of your article and those cute, base-10 score bubbles. Seriously fine work!

Great article on CSS specificity! An explanation isn’t even necessary, the pics suffice. But Chris, in light of Eric Meyer’s correction, why don’t you fix your pics? Remove the pluses and add the commas.

Hi Chris! Great post. I was wondering if you could eventually post all your custom class CSS-Tricks in one neat post/page. For example you mentioned in this post your .last {} class trick which you made when you boarder/float issues. I think it could be usefully to put those items in the CSS reset file and you could use them over and over.

I have in mind that the !important rule should be avoided in author stylesheets because they also overwrite declarations within a user stylesheet. As a user stylesheet should be considered more important (if a user has a special stylesheet there is a reason for this). Using !important makes it also harder for yourself to override this declaration further down in a stylesheet.

As always, there are more solutions to your problem shown above. If a style is important for the whole list it is better to apply the styles to the list and not to the list items. If you apply the color to ul#summer-drinks there is no problem applying a different color to .favorite. You can avoid most of the specificity problems by just making use of inheritance.

One good reminder is to avoid being more specific than you need, sometimes it can help performance and also makes maintenance/re-use easier. You don’t need the “ul” on “ul#summer-drinks” since you can only have one ID per page.. having less and more efficient selectors make your page render faster.

Another thing is to always put elements (e.g. “p, a, h1”) and generic classes (e.g. “last”) before the other rules, it’s easier to understand what will be overwritten..

This is one of my favorite articles about CSS specificity. I never really was able to really understand what this was all about even when I was going to school The teachers I had didn’t really explain it all that well. It is amazing that CSS really is all that powerful. I don’t even know anything about CSS5 so I have a long ways to go.

Specificity is one of the most confusing aspects of CSS. Your article is the best I’ve seen at explaining it, an excellent job.

I’m concerned about people finding this article. When I first stumbled on to the issue several years ago, I had no idea it was called “specificity.” I was simply trying to find out why styles attached to an id were overriding styles defined by class on an element contained within the id’ed element!

It would be very interesting to learn what people searched for when they were trying to get past this and then make sure the article was responsive to such searches.

!important applies to the element it is assigned to, not child elements. I believe <a> is considered a child of <p> in this case. Any text within the parent element would be red regardless of what styles were applied to the universal p selecter; However <a> would retain it’s specified styles.

Using the Bootstrap boilerplate from Initializr.com, there is a built-in style, which appears to have a specificity of 0,0,1,0:

.col-lg-4 {
width: 33.33333333333333%;
}

I wanted to give it rounded corners with a border (no problem) and give it a little room between columns so the borders don’t touch. I created this code, which to me seems to have a specificity of 0,0,2,0:

.col-lg-4.rounded {
margin-right:0.5%;
width: 32.83333333333333;
}

According to Firebug, both selectors are considered, but the non-.rounded loses to the regular one. So, I tried creating the inverse, which to me seems to also have a specificity of 0,0,2,0:

.col-lg-4:not(.rounded) {
width: 33.33333333333333%;
}

Sure enough, it beats out the plain one, apparently because it has more specificity.
I also tried changing around the order of the selectors, inline vs. included, and the order the classes are listed (.rounded.col-lg-4), and nothing made a difference. I did my testing in Chrome.

So it makes me wonder why two classes on the same element along with a selector that targets both, not have higher specificity than a selector targeting only one? Or maybe my math is just wrong?

I found the issue. There is a @media selector above that covered the style I was trying to override. Therefore, I suppose that means that @media has a very high value, though I’m not exactly sure where it would fall into this hierarchy. Perhaps that information could be added to this article?

This comment thread is closed. If you have important information to share, please contact us.