No Login Data Private Local Save

CSS Specificity Battle - Online Fight Two Selectors

11
0
0
0

CSS Specificity Battle

Pit two CSS selectors against each other — see which one packs more weight

Challenger
VS
Opponent
Specificity Level Challenger VS Opponent
a — Inline 0 a 0
b — ID — b —
c — Class / Attr / Pseudo-class — c —
d — Element / Pseudo-element — d —
Total Score — 🏆 —

Quick Preset Battles — click to load:

Frequently Asked Questions

CSS specificity is the algorithm browsers use to decide which CSS rule applies when multiple rules target the same element. Think of it as a weight system — selectors with higher specificity override those with lower specificity, regardless of source order (unless !important is involved). Understanding specificity is essential for debugging styling conflicts and writing maintainable CSS.

Specificity is represented as a 4-part value: (a, b, c, d).
  • a — Inline styles (style="..."). Always 1 if inline, 0 otherwise.
  • b — Count of ID selectors (#header).
  • c — Count of class selectors (.btn), attribute selectors ([type="text"]), and pseudo-classes (:hover, :nth-child()).
  • d — Count of element selectors (div, p) and pseudo-elements (::before, ::after).
Comparison goes left to right: (0,1,0,0) beats (0,0,99,99) — one ID outweighs any number of classes.

An ID selector (#example) has specificity (0,1,0,0), while a class selector (.example) has (0,0,1,0). The ID always wins because the b level is compared first. In fact, a single ID outweighs any number of classes, attributes, or pseudo-classes combined.

The universal selector * adds zero specificity — it contributes (0,0,0,0). It's often used for CSS resets or global styles precisely because it's so easy to override. Similarly, combinators like >, +, ~, and the descendant space add no specificity.

  • :not() — The negation pseudo-class itself adds no specificity, but selectors inside the parentheses are counted normally. :not(.foo) contributes (0,0,1,0).
  • :is() — Takes the specificity of its most specific argument. :is(#a, .b, div) has specificity (0,1,0,0).
  • :where() — Always has zero specificity regardless of its arguments. Great for writing low-specificity base styles.
  • :has() — Behaves like :is(), taking the highest specificity among its arguments.

When specificity is tied, the source order decides — the rule that appears later in the CSS file wins. This is why you should generally place more specific overrides after base styles, or rely on specificity rather than source order for predictable results.

!important doesn't change specificity — it bypasses the normal cascade entirely. An !important declaration wins over any normal declaration, regardless of specificity. When two !important rules conflict, specificity (and then source order) determines the winner. Overusing !important is widely considered bad practice as it makes CSS harder to debug and maintain.

  • Prefer classes over IDs for styling — they're reusable and keep specificity low.
  • Avoid deeply nested selectors like .page .content .sidebar .widget h3.
  • Use BEM or similar naming conventions to flatten specificity.
  • Reserve !important for utility overrides only (e.g., .d-none).
  • Use :where() for base styles that should be easily overridable.
  • Regularly audit specificity with tools like this battle simulator!