Skip to main content

Specificity & Cascade

How Specificity is Calculated

Specificity is a weight assigned to a selector, expressed as (a, b, c):

ComponentWeightExamples
a – Inline styles1,0,0style="color: red"
b – IDs0,1,0#header
c – Classes, attributes, pseudo-classes0,0,1.nav, [type="text"], :hover
Universal *, combinators, :where()0,0,0No 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:

  1. Origin & Importance – User-agent < Author < Author !important < User !important
  2. Specificity – Higher weight wins
  3. 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; }