The Cascade & Specificity

When several rules set the same property on the same element, only one value wins. The cascade is the algorithm that decides which, based on origin, importance, layers, specificity and order. Understanding it ends the frustration of "why isn't my CSS working?".

Rule 1: later wins (when everything else is equal)

Try it yourself
Result

Between two rules with equal weight, the one that appears last in the CSS wins. This applies across files too: a stylesheet linked later overrides one linked earlier.

Rule 2: specificity beats order

Try it yourself
Result

Even though p comes last, more specific selectors win regardless of order.

Calculating specificity

Specificity is a score with three columns, compared from left to right:

ColumnCountsExample
A — ids#id#nav → (1,0,0)
B — classes, attributes, pseudo-classes.class, [type], :hover.btn:hover → (0,2,0)
C — types, pseudo-elementsp, ::beforeul li a → (0,0,3)

A single id (1,0,0) beats any number of classes (0,10,0), and one class beats any number of type selectors. The universal selector * and combinators add nothing.

SelectorSpecificity
li(0,0,1)
ul li(0,0,2)
.item(0,1,0)
ul li.item:hover(0,2,2)
#menu .item(1,1,0)

Browser developer tools show each selector's specificity when you hover it in the Styles panel.

Inline styles and !important

Try it yourself
Result

Inline style attributes beat any selector. !important on a declaration beats everything that isn't also important. It's an escape hatch, but it creates a war of escalating overrides — the only way to beat !important is another !important with higher specificity. Reserve it for utilities that must always win and for overriding third-party CSS you can't edit.

The full cascade order

From lowest to highest priority, the browser considers:

  1. Origin — browser defaults, then user settings, then author (your) styles.
  2. Cascade layers — styles in later @layers beat earlier layers; unlayered styles beat layered ones (lesson 45).
  3. Specificity — as above.
  4. Order of appearance — the last one wins.

!important reverses the origin and layer order, which is how users' accessibility settings can override sites.

Keeping specificity low

Most CSS problems come from specificity creeping upward. Habits that prevent it:

  • Style with single classes; avoid ids in CSS.
  • Avoid long descendant chains like .page .sidebar ul li a.
  • Don't qualify classes with types (div.card) unless necessary.
  • Use :where() for zero-specificity defaults that are easy to override (lesson 43).
  • Organise with cascade layers instead of fighting with !important.

Debugging "my CSS isn't applied"

  1. Inspect the element and look at the Styles panel.
  2. Is your rule listed at all? If not, the selector doesn't match (typo, wrong class, stylesheet not loaded).
  3. Is it crossed out? A more specific or later rule is winning — the panel shows which.
  4. Is it crossed out with a warning icon? The value or property is invalid.

Try it yourself

Predict the colour of each button, then check. Change one selector to change the winner.

Try it yourself
Result