CSS Specificity
debt(d5/e5/b7/t7)
Closest to 'specialist tool catches' (d5). The term's detection_hints list stylelint and css-specificity-graph as tools that can catch specificity issues. These are specialist tools that can detect !important overuse, deeply nested selectors, and ID selectors for styling, but they're not default linters that run automatically in most projects.
Closest to 'touches multiple files / significant refactor' (e5). The quick_fix suggests keeping specificity low and flat with single class selectors, avoiding IDs and !important. However, fixing specificity debt in an existing codebase often requires refactoring selectors across multiple stylesheets, component files, and potentially restructuring the CSS architecture. It's not a one-line fix when specificity wars have already begun.
Closest to 'strong gravitational pull' (b7). CSS specificity applies to all web contexts and affects every styling decision. Once high-specificity patterns (ID selectors, nested selectors, !important) are established, they create a gravitational pull where every new style must fight against or escalate the existing specificity. The why_it_matters field explicitly states this leads to 'increasingly complex selector chains' — a compounding structural tax that shapes how all future CSS is written.
Closest to 'serious trap' (t7). The misconception field explicitly states that developers believe '!important is a valid tool for fixing specificity issues' when it actually creates more debt. This contradicts intuition from other domains where 'override' mechanisms solve conflicts cleanly. The common_mistakes list multiple traps: inline styles beating stylesheets, ID specificity being unexpectedly high, and nested selectors creating brittle specificity chains.
Also Known As
TL;DR
Explanation
Specificity is calculated as (ID count, class/attribute/pseudo-class count, element/pseudo-element count). Inline styles override everything except !important. #id (1,0,0) > .class (0,1,0) > div (0,0,1). When specificity ties, the last rule in source order wins. !important overrides all specificity but creates maintenance nightmares. The best practice is keeping specificity as low as possible, using classes (not IDs) for styling, and avoiding !important.
Common Misconception
Why It Matters
Common Mistakes
- Using ID selectors (#header) for styling — IDs have very high specificity and are hard to override.
- Adding !important to fix a specificity conflict — this is a symptom, not a fix.
- Deeply nested selectors (.nav ul li a:hover) — high specificity, brittle, hard to override.
- Not understanding that inline style specificity is higher than any stylesheet rule (except !important).
Code Examples
/* Specificity escalation — each override needs a stronger selector: */
#header .nav li a { color: blue; } /* (1,1,2) */
#header .nav li a.active { color: red; } /* (1,2,2) — specificity war */
#header .nav li a.active:hover { color: green !important; } /* gave up */
/* Low specificity — easy to override, easy to maintain: */
.nav-link { color: blue; } /* (0,1,0) */
.nav-link--active { color: red; } /* (0,1,0) — same specificity, last wins */
.nav-link--active:hover { color: green; } /* (0,2,0) — minimal increase */