CSSTidy CSS Formatter

CSS Specificity, Computed: What :is(), :not() and :where() Actually Add

CSSTidy Guides · Updated 2026-10-30 · All guides

When two rules set the same property on the same element, the cascade compares origin and importance first, then specificity, then source order. Specificity is a triple, compared left to right. The specificity calculator computes it for a list of selectors; this page is the rulebook it implements (Selectors Level 4).

The three columns

ColumnCountsExampleScore
ids#id#nav1,0,0
classes.class, [attr], :pseudo-classa.btn:hover[href]0,3,1
typesdiv, ::pseudo-elementul li::before0,0,3

*, combinators (>, +, ~, space) and the :where() function add nothing. The columns do not carry: #a (1,0,0) beats a selector of eleven classes (0,11,0) because the first column is compared first. The old story that 256 classes overflow into an id was true of a 1990s byte-per-column implementation and is not true of current engines.

The functions that change the arithmetic

SelectorScoreRule
a:not(.x, #y)1,0,1:not() is replaced by its most specific argument, not the sum.
:is(h1, .title) span0,1,1Same rule for :is(). The h1 branch is ignored because .title is more specific.
:where(#app) p0,0,1:where() is always zero, whatever is inside it.
li:nth-child(2n+1 of .a, #b)1,1,1One pseudo-class, plus the most specific selector after of.
a:before0,0,2The legacy single-colon form is still a pseudo-element.

The consequence of the :is() rule: the score of a list is the score of its heaviest member, even when the element matched the light one. :is(h1, #hero) span costs 1,0,1 on every h1 span too.

Why :where() exists

A reset or a component library that ships :where(.btn) instead of .btn has specificity 0,0,0 for that part, so any rule you write afterwards wins without a specificity fight. It is the supported way to write a default that is meant to be overridden.

What is outside the score

  • Inline style="" outranks any selector.
  • !important is a separate layer: an important declaration beats all normal ones, and between two important declarations specificity decides again.
  • @layer: for normal declarations a later layer beats an earlier one regardless of specificity, and unlayered styles beat all layers. Specificity only matters inside one layer.
  • Nesting (&): a nested selector's score is computed from the rule it expands to, so the calculator flags & instead of guessing.

Reading the calculator's output

Selectors are ranked most-specific first; on a tie the rule written later is listed first, because it wins. Paste a whole stylesheet and the tool extracts every selector, including ones inside @media.

Developer Sponsor / Partner
Copied to clipboard!