CSS Selectors: Specificity

Think of specificity as a score or rank that determines which style declarations are ultimately applied to an element. The universal selector (*) has low specificity. ID selectors are highly specific. Descendant selectors such as p img and child selectors such as .panel > h2 are more specific than type selectors such as p, img, or h1.

count the number of class selectors, attribute selectors, and pseudo-classes in the selector (= B)

count the number of type selectors and pseudo-elements in the selector (= C)

ignore the universal selector

These A, B, and C values are then combined to form a final specificity value. An ID selector such as #foo has a specificity of 1,0,0. Attribute selectors, such as [type=email] and class selectors such as .chart have a specificity of 0,1,0. Adding a pseudo-class such as :first-child (for example, .chart:first-child) gives us a specificity of 0,2,0. But using a simple type or element selector such as h1 or p only gives us a specificity of 0,0,1.

These two rule sets are similar, but they are not the same. The first selector, ul#story-list > .bookreview, contains a type selector (ul), an ID selector, (#story-list), and a class selector (.bookreview). It has a specificity value of 1,1,1. The second selector, #story-list > .book-review only contains an ID and a class selector. Its specificity value is 1,1,0. Even though our #story-list > .book-review rule succeeds ul#story-list > .bookreview, the higher specificity of the former means that those elements with a .book-review class will be green rather than orange.

Pseudo-classes such as :link or :invalid have the same level of specificity as class selectors. Both a:link and a.external have a specificity value of 0,1,1. Similarly, pseudo-elements such as ::before and ::after are as specific as type or element selectors. In cases where two selectors are equally specific, the cascade kicks in. Here’s an example:

a:link {
color: #369;
}
a.external {
color: #f60;
}

If we applied this CSS, every link would be slate blue except for those with class="external" applied. Those links would be orange instead.

Keeping specificity low helps prevent selector creep, or the tendency for selector specificity and length to increase over time. This often happens as you add new developers to a team, or new forms of content to a website. Selector creep also contributes to long-term maintenance headaches. You either end up using more specific selectors to override other rule sets, or needing to refactor your code. Longer selectors also increase the weight of your CSS files.

We discuss strategies for keeping specificity low in Chapter 2.

Conclusion

After reading this chapter, you should have a good understanding of CSS selectors. Specifically, you should now know how to:

use selectors to apply CSS to particular elements, pseudo-elements, and pseudo-classes

Tiffany B. Brown is a freelance web developer and technical writer based in Los Angeles. Brown offers web development and consulting services to larger agencies and small businesses. A former member of the Opera Software developer relations team, Brown is also co-author of SitePoint's JumpStart HTML5 book. She sporadically writes about web development technology on her blog. You can follow her on Twitter at @webinista.