ESC

Type to search the knowledge base.

Cascade & Specificity

How CSS decides the winner — origin, importance, layers, specificity, and order — in human terms.

beginner2 min read
  • css
  • cascade
  • specificity

When two declarations target the same property on the same element, the cascade picks one. Specificity is a step in that fight — not the whole rulebook.

If your debugging strategy is “add classes until it works, then !important,” this is the reset button.

Order of battle (simplified, author styles)

  1. Cascade layers (@layer) — later layers beat earlier ones for normal declarations
  2. Specificity of the selector
  3. Source order — last tied rule wins
  4. Inline styles sit high on the specificity ladder
  5. !important flips a lot of origin/layer rules — treat it as a last resort

User-agent and user styles also participate; most app work is author CSS.

Specificity as a scoreboard

Rough tuple: (inline, IDs, classes/attributes/pseudo-classes, elements/pseudo-elements).

Selector Rough weight
div elements
.card one class
.card.featured two classes
#hero one ID
button:hover class-ish + element
.nav a { color: blue; }      /* class + element */
a.nav-link { color: red; }   /* same ballpark — later wins if equal */

:where() contributes zero specificity — great for base styles you want to override easily.
:is() takes the most specific argument inside it — easy footgun with IDs.

Layers beat selector wars

@layer reset, base, components, utilities;

@layer components {
  .button { color: white; }
}

@layer utilities {
  .text-accent { color: var(--accent); }
}

A utility in a later layer can win even with a lighter selector. That’s how design systems stay sane.

Inheritance ≠ cascade

  • Cascade chooses among declarations for a property.
  • Inheritance fills inheritable properties (color, font-*, …) when nothing was declared.

margin does not inherit. color does. inherit / initial / unset / revert are the explicit controls.

Habits that age well

  1. Prefer boring class selectors
  2. Reach for layers before escalating specificity
  3. Avoid IDs in app CSS
  4. Reserve !important for rare utilities or third-party overrides
  5. Theme with custom properties instead of selector cage matches

Debug checklist (DevTools)

  1. Is the property applied at all?
  2. Which rule is struck through?
  3. Layer or !important involved?
  4. Did a later file silently win?

Further reading

Related guides