Provixx

CSS Specificity Calculator

Calculate and visualize CSS selector specificity instantly. See exactly why one rule beats another.

[Inline] Inline Style
[ID] IDs
[Class] Classes, Attributes & Pseudo-classes
[Element] Elements & Pseudo-elements
[Zero] Ignored (:where, *, combinators)

Selector

Live Input
/ focus Ctrl+↵ calc Esc clear
Try an example:

Result

1 - 2 - 2

Compare Selectors

Head to Head
A Selector A 1 - 1 - 0
B Selector B 0 - 2 - 2
Battles:

A Wins

Winner

A wins because it has 1 ID and B has 0. The ID column is compared first.

Category Selector A Selector B Verdict / Diff
Full CSS Cascade Order Reminder
1. !important (origins/layers) → 2. Inline Style → 3. Specificity (a,b,c) → 4. Source Order (Later wins)

When !important is declared on both sides, the standard specificity comparison still applies between them. Cascade layers (@layer) and origins (user-agent vs author) also affect final styles; this tool evaluates selector specificity along with the inline and !important flags above.

Analyze a CSS File

Stylesheets & Snippets
Privacy Guaranteed: Your CSS never leaves your browser. All parsing and specificity analysis execute 100% locally client-side.
Drag & drop a .css file here, or

Learn CSS Specificity

Specification & Best Practices
1. What is CSS specificity?

CSS specificity is the weight algorithm browsers use to resolve conflicting CSS declarations targeting the same HTML element. When two or more selectors match an element, the declaration associated with the most specific selector wins and applies its styles.

A Simple Analogy: Think of specificity like weight classes in boxing or military ranks. A single heavyweight outmatches any number of lightweights, just as a single general outranks any battalion of privates. In CSS, an ID selector outranks any number of classes, and a class outranks any number of bare element tags.

Example: ID outranks chained classes
2. How is it calculated? (The 3-Column Tuple)

Specificity is measured as a 3-part tuple: (A, B, C). Each category contributes to its designated column:

Category Column Target Selectors Contribution
IDs Column A #header, #nav +1, 0, 0
Classes & Attributes Column B .card, [type="text"], :hover +0, 1, 0
Elements & Pseudos Column C div, p, ::before, ::after +0, 0, 1

Comparison Rule: Tuples are compared lexicographically from left to right. Column A is evaluated first. If tied, Column B is evaluated. Only if both A and B are equal is Column C checked.

Example: #header .nav ul li.active → Specificity 1 - 2 - 2
3. What is ignored? (The Non-Base-10 Rule)

These parts contribute [0, 0, 0] to specificity:

  • Universal selector: * adds 0
  • Combinators: Descendant (space), child (>), adjacent sibling (+), and general sibling (~) add 0
  • The zero-specificity pseudo-class: :where(...) always contributes [0, 0, 0] regardless of what is inside it.

CRUCIAL WARNING: Specificity is NOT base-10!
A very common beginner trap is thinking (0, 1, 0) = 10 and (0, 0, 11) = 11. Numbers in CSS specificity never carry over into adjacent columns. 11 classes (0 - 11 - 0) will never beat 1 ID (1 - 0 - 0).

Example: 11 chained classes (0 - 11 - 0)
4. Special Selectors (CSS Selectors Level 4 Rules)

Modern functional pseudo-classes follow recursive evaluation rules specified in CSS Selectors Level 4:

Selector Specificity Contribution Example
:is(A, B) Takes specificity of the most specific argument :is(#nav, .menu) → [1, 0, 0]
:not(A, B) Takes specificity of the most specific argument :not(.disabled, a) → [0, 1, 0]
:has(A, B) Takes specificity of the most specific argument div:has(> #hero) → [1, 0, 1]
:where(...) Always zero: [0, 0, 0] :where(#app, .btn) → [0, 0, 0]
:nth-child(An+B of S) [0, 1, 0] + max specificity of selector list S :nth-child(odd of .item) → [0, 2, 0]
::slotted(S) [0, 0, 1] + max specificity of selector S ::slotted(.slot-item) → [0, 1, 1]
:host(S) [0, 1, 0] + max specificity of selector S :host(.active) → [0, 2, 0]
Example: Complex :is() and :not() combinations
5. Inline styles, !important and the Cascade Order

Selector specificity is only one step in the broader CSS Cascade algorithm. The definitive order of precedence is:

  1. !important declarations: Overrides inline styles and normal specificity rules.
  2. Inline styles: Properties set directly on elements (style="...") beat all external and internal stylesheet rules.
  3. Selector Specificity: The highest (A, B, C) tuple wins.
  4. Source Order: When specificity is identical, the rule appearing later in the CSS wins.

Important note: When !important is applied to both conflicting rules, the standard specificity comparison still decides which one wins!

Example: Compare buttons in Head to Head
6. Architectural Best Practices
  • Keep specificity flat and low: Prefer single or double class selectors (e.g., BEM .card__title). Low specificity ensures styles can be overridden cleanly anywhere.
  • Avoid IDs for styling: Reserve IDs for HTML anchors and JS hooks. Using an ID in CSS forces you to use another ID or !important to override it.
  • Avoid !important: Treat !important as a code smell. It creates maintainability deadlocks.
  • Use :where() for resets and base styles: Wrapping design system primitives in :where(...) keeps their specificity at 0, allowing consumer components to override them without resistance.
  • Adopt CSS Cascade Layers (@layer): Use layers (e.g., @layer reset, base, components, utilities;) to control priority across large codebases without inflating selector specificity.
  • Keep selector chains short: Avoid over-qualifying elements like div.card ul.list li.item; write .list__item instead.
Example: Zero-specificity reset using :where()
7. Common Mistakes & Pitfalls
  • Over-qualifying selectors: Writing ul.nav or div.sidebar instead of just .nav or .sidebar. This adds unnecessary element specificity and couples your CSS to HTML tag choices.
  • Chaining excessive classes: Writing .card.featured.active.primary.large to win an override battle rather than refactoring CSS architecture.
  • Forgetting that source order breaks ties: If two selectors have identical specificity (e.g., both 0 - 1 - 0), whichever rule comes later in the stylesheet wins.
  • Assuming :where() takes argument specificity: :where() is specifically designed to always have 0 specificity; use :is() if you want argument specificity.
Example: Over-qualified nested chain
Engine Self-Test (CSS Selectors Level 4 Specification)
30 / 30 Passed
Running 30 specification cases...
Status Selector Expected Specificity Actual Specificity Notes / Verdict