Chapter 2 · Practice 1 of 4
Keep specificity low and flat
Why it matters
When two rules set the same property, the one with higher specificity wins, regardless of where it appears. Codebases that use IDs, long descendant chains and !important end up in an arms race, where every new rule must be more specific than the last.
Rules that keep specificity flat:
- Style with classes, not IDs. One class is easy to override with another class.
- Avoid long selectors like
.sidebar .nav ul li a. Give the element a class instead. - Use
:where()to remove specificity from parts of a selector. Everything inside:where()counts as zero, so defaults stay easy to override. - Know that
:is(),:not()and:has()take the specificity of their most specific argument. One ID inside:is()makes the whole selector as strong as an ID.
Avoid
- IDs in selectors for styling
- Adding
!importantto win a specificity fight
Example
/* Hard to override: an ID plus three elements */
#main nav ul li a { color: navy; }
/* Easy to override: one class */
.nav-link { color: navy; }
/* Zero specificity default: any class beats it */
:where(.prose) a { color: var(--color-link); }