CSS specificity: pick a number, any number

Posted on

I've always thought I had a good enough understanding of CSS specificity to get by. IDs trump classes, classes trump tag names etc. But I'm ashamed to say I have never read up on the exact rules.

While twiddling with the CSS for this website recently I landed on an MDN article Specificity and decided to give it a read. Here follows some tidbits I found interesting.

3 columns, 3 numbers

The CSS specificity algorithm generates 3 columns of numbers for a CSS rule's selector. The columns represent, from left to right: IDs, classes, and types.

You can see the specificity that a selector has by hovering over it in your web browser's developer tools. It will display a value like Specificity (0, 1, 1)

In this example it would mean that the selector has 0 IDs, 1 class, and 1 type. But what is considered an ID, class, or type? The following table gives some examples:

Column Selector examples
ID #content
Class .button, :hover, [name="surname"]
Type a, ::before

The class column has the most variation in values, and I recommend reading the MDN article Specificity for the complete information.

So going back to my example of Specificity (0, 1, 1), the selector that is weighted as such might look like: .nav a, because as you can see it has one class, and one tag in the selector.

So who wins?

The ID column has the greatest weight, then the Class column, and finally the Type column. So #content trumps .button which trumps a.

When two or more selectors match an element, the specificity columns are compared from left to right.

The selector with the greatest number in the ID column will win. If all selectors have the same ID column value, then the Class column is compared. If no selector has a higher Class column value then finally the Type column is compared.

For example, Specificity (0, 1, 0) beats Specificity (0, 0, 2).

Examples

  • #content a Specificity (1, 0, 1) is more specific than .content a Specificity (0, 1, 1)

  • a:hover Specificity (0, 1, 1) is more specific than .link Specificity (0, 1, 0)

  • article p Specificity (0, 0, 2) is more specific than p Specificity (0, 0, 1)

  • p.article-text Specificity (0, 1, 1) is more specific than article p Specificity (0, 0, 2)

When multiple selectors have equal specificity, the rule that appears last in the CSS order will be the one that is applied.

Furthermore, if a matching selector is in a stylesheet which has a greater origin precedence, then that selector will win regardless of specificity.

For example, a selector in an author's stylesheet (the website's stylesheet) will overrule a selector in a stylesheet that belongs to the user or the user agent (browser). Using !important changes this!

The MDN article Introduction to the CSS cascade has more on stylesheet origin precedence.

Wrapping up

So those are some of the finer details of CSS specificity I learned recently.

There is a lot I left out and a lot I probably don't know, so I thoroughly recommend reading more official sources on the topic.

Thanks for reading!