Specificity & Cascade
How Specificity is Calculated
Specificity is a weight assigned to a selector, expressed as (a, b, c):
| Component | Weight | Examples |
|---|---|---|
a – Inline styles | 1,0,0 | style="color: red" |
b – IDs | 0,1,0 | #header |
c – Classes, attributes, pseudo-classes | 0,0,1 | .nav, [type="text"], :hover |
Universal *, combinators, :where() | 0,0,0 | No specificity |
/* (0,1,1) — 1 ID + 1 class */
#sidebar .link { color: blue; }
/* (0,0,2) — 2 classes */
.sidebar .link { color: red; }
/* #sidebar .link wins */
The Cascade Order
When specificity ties, the browser resolves by:
- Origin & Importance – User-agent < Author < Author
!important< User!important - Specificity – Higher weight wins
- Source Order – Later declaration wins
@layer (Cascade Layers)
Control cascade ordering without fighting specificity:
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; box-sizing: border-box; }
}
@layer components {
.btn { padding: 8px 16px; }
}
@layer utilities {
.mt-4 { margin-top: 1rem; }
}
Layers declared earlier have lower priority. Unlayered styles beat all layers.
:is(), :where(), :has()
/* :is() — takes highest specificity of its arguments */
:is(h1, h2, h3) { font-weight: 700; }
/* :where() — zero specificity (great for resets) */
:where(h1, h2, h3) { margin: 0; }
/* :has() — parent selector */
.card:has(img) { padding: 0; }
.form:has(:invalid) { border-color: red; }