Specificity Rules
Specificity is a scoring system that determines which CSS rule wins when multiple rules target the same element with equal source-order priority. It's commonly represented as four comma-separated numbers.
Scoring, from highest to lowest weight:
/* Inline style: always wins over any selector (not counted in this 4-part system) */
/* IDs: 1 point each */
#header { } /* specificity: 0,1,0,0 */
/* Classes, attributes, pseudo-classes: 1 point each */
.nav-item { } /* specificity: 0,0,1,0 */
[type="text"] { } /* specificity: 0,0,1,0 */
:hover { } /* specificity: 0,0,1,0 */
/* Type selectors, pseudo-elements: 1 point each */
p { } /* specificity: 0,0,0,1 */
::before { } /* specificity: 0,0,0,1 */
/* The universal selector (*) and combinators contribute 0 */
* { } /* specificity: 0,0,0,0 */
Combined selectors add up their individual scores:
#sidebar .card p { }
/* 1 ID + 1 class + 1 type = 0,1,1,1 — beats any rule below */
.sidebar .card p { }
/* 3 classes... wait, 2 classes + 1 type = 0,0,2,1 */
A rule with 0,1,1,1 beats a rule with 0,0,2,1 because the comparison happens left to right: first compare ID counts (1 vs 0 — the first rule already wins here), and only move to the next column if there's a tie.
Practical guidance to avoid specificity wars:
- Prefer classes over IDs for styling (reserve IDs for JavaScript hooks and anchor links).
- Avoid deeply nested selectors (
.a .b .c .d) — they're hard to override later and tightly couple CSS to a specific HTML structure. - Avoid
!importantexcept as a last resort or in narrow utility classes designed to always win. - When two rules with the same specificity conflict, the one written later in the file wins — so file/import order matters too, not just specificity math.