CSS Specificity and Cascade: How to Keep It Predictable
When two rules target the same element, specificity and cascade order decide which one wins. Misused, they lead to override wars and !important hacks. This post explains how they work and how to keep your CSS predictable and maintainable.
Specificity: the score
Specificity is a score (inline > ID > class > type). A single ID beats any number of classes; a single class beats any number of types. Pseudo-classes (e.g. :hover) count like classes; * and :where() have zero specificity.
Rule of thumb: Prefer classes (and custom properties). Avoid IDs in CSS and avoid long chains of selectors (e.g. .page .sidebar .card .title) unless you have a clear reason—they make overrides harder and specificity higher.
Cascade order: same specificity
When specificity is equal, order wins: later rules override earlier ones. So the order of your stylesheets and rules matters. In component-based apps, load order (e.g. global then components) and where you put overrides (e.g. in a theme file after base) should be intentional.
How to keep it predictable
- One main class per component: Style by a single block class (e.g.
.card) and use descendants or BEM-style modifiers. That keeps specificity low and overrides explicit. - Avoid IDs for styling: Use IDs for fragment links and JS hooks, not for CSS. That keeps specificity manageable.
- Use custom properties for overrides: Instead of overriding a long selector, override a variable (e.g.
--card-bg) on a parent. The component uses the variable; the parent controls the value. - Prefer
() for resets or low-priority rules: :where(.reset-list)has zero specificity so any component class can override it without fighting.
!important
!important overrides specificity and order. Use it only for true overrides (e.g. utility that must win, or critical fix). Don’t use it as a default; it makes future overrides harder and hides design debt.
Summary
- Specificity (inline > ID > class > type) and cascade order determine which rule wins; prefer classes and avoid long selector chains.
- Keep it predictable: One main class per component, avoid IDs for styling, use variables for theming, use
:where()when you want low specificity. - !important is a last resort; fix structure and specificity first. Predictable specificity and cascade keep CSS maintainable at scale.