CSS Specificity Wars — Understanding Selector Precedence

Understand how CSS specificity determines which styles win. Learn to calculate specificity, resolve conflicts, and avoid the !important escape hatch with practical examples.

Advanced Patterns

Detailed Explanation

CSS Specificity Wars

When multiple CSS rules target the same element, specificity determines which one wins. Understanding specificity is crucial for debugging styling issues and writing maintainable CSS.

The Specificity Hierarchy

Specificity is calculated as a three-part vector (a, b, c):

Component Weight Examples
a — ID selectors Highest #header, #nav
b — Classes, attributes, pseudo-classes Medium .nav, [type], :hover
c — Elements, pseudo-elements Lowest div, ::before

Calculating Examples

*                    → (0, 0, 0)
p                    → (0, 0, 1)
.intro               → (0, 1, 0)
p.intro              → (0, 1, 1)
#header              → (1, 0, 0)
#header .nav li      → (1, 1, 1)
#header .nav li.active a:hover
                     → (1, 3, 2)

Resolution Rules

  1. Higher specificity always wins, regardless of source order
  2. Equal specificity? Last rule in source order wins
  3. Inline styles (style="") beat all selectors
  4. !important beats everything (including inline styles)

Avoiding Specificity Problems

  • Do: Use flat, class-based selectors (.nav-item not #nav > ul > li)
  • Do: Use BEM naming (.block__element--modifier)
  • Don’t: Nest selectors more than 3 levels deep
  • Don’t: Use IDs for styling
  • Don’t: Use !important (except for utility classes)

CSS Layers (@layer)

CSS Cascade Layers provide a new way to manage specificity:

@layer base, components, utilities;

@layer base { p { color: black; } }
@layer components { .text-red { color: red; } }
@layer utilities { .text-blue { color: blue; } }

Layers defined later override earlier ones, regardless of selector specificity within each layer.

Use Case

Understanding specificity is essential for every front-end developer. It explains why styles sometimes don't apply as expected, why overriding third-party CSS can be difficult, and why CSS architectures like BEM exist. Specificity debugging is a daily task in large codebases, component library development, and when integrating multiple CSS sources (frameworks, themes, custom styles).

Try It — CSS Selector Tester

Open full tool