The Three-Number System
Every CSS selector produces a specificity score expressed as three numbers: (IDs, Classes+Attributes+Pseudoclasses, Elements+Pseudoelements). Higher numbers win. The comparison is left-to-right — a selector with any ID beats a selector with any number of classes, regardless of class count.
Examples:
div→ (0, 0, 1).card→ (0, 1, 0)#header→ (1, 0, 0)#header .nav a→ (1, 1, 1)
Common Traps
!important overrides all specificity and source order. Once it appears in a codebase it spreads — you need !important to override !important. Avoid it except for utility classes designed to always win (like .hidden { display: none !important }).
Inline styles have implicit specificity (1, 0, 0, 0) — higher than any stylesheet selector. Avoid inline styles in component-based UIs.
Chained class selectors (.card.featured) have specificity (0, 2, 0) and can cause surprising overrides of ID-based selectors in some architectures.
Writing Less-Specific CSS
Flatter selectors are easier to override and reason about. Prefer a single class selector over a tag+class selector. Avoid nesting selectors more than two levels deep. In component-based frameworks, scope styles to the component rather than increasing specificity to avoid collisions.
A specificity calculator shows the score for any selector before you write it.