Developer Tools

CSS Specificity Calculator

Compare selectors without guessing which number matters most. Enter selectors on separate lines or in a comma-separated list to see their ID, class, and type counts, with optional sorting from strongest to weakest.

Free online tool

Loading tool…

A = IDs; B = classes, attributes, and pseudo-classes; C = types and pseudo-elements. Compare left to right, without carrying digits.

Selector comparison

SelectorABCTuple
#main a1011,0,1
:is(.card, #featured) a1011,0,1
article .card a:hover0220,2,2
:where(#main) .card a0110,1,1

The largest tuple wins only after origin, importance, and cascade layer are equal. Tied selectors require scope proximity and then source order to resolve the cascade. A selector must match the element to compete.

:where() contributes zero. :is(), :not(), and :has() use the highest specificity of their argument list. :nth-child(... of ...) adds a pseudo-class plus the highest argument specificity. Inline styles and declarations such as !important are outside this selector comparison.

Selectors are parsed locally with the specificity library.

GET STARTED

How to use the CSS Specificity Calculator

  1. 01

    Paste selectors without CSS declarations. Use a new line or a top-level comma to separate them.

  2. 02

    Read each A,B,C tuple from left to right: IDs, classes and similar selectors, then types and pseudo-elements.

  3. 03

    Compare the sorted rows or export a tab-separated table. Check the other cascade conditions before deciding which declaration wins.

Examples

An ID outweighs many classes

#main a has specificity 1,0,1. .layout .card a:hover has 0,3,1. The ID selector wins this comparison when all earlier cascade conditions are equal.

Zero-weight grouping

:where(#main) .card a has specificity 0,1,1 because :where() and its arguments add zero. :is(.card, #featured) a has 1,0,1 because :is() takes its most specific argument.

Selectors Level 4 exceptions

:is(), :not(), and :has() contribute the highest specificity among their argument selectors rather than a separate pseudo-class point. :where() contributes zero, including its arguments. :nth-child() and :nth-last-child() contribute one pseudo-class plus the most specific selector in an optional of-list. A universal selector and combinators do not add specificity.

Specificity is one part of the cascade

The tuple is compared lexicographically. Ten classes do not become one ID, and there is no decimal score. Origin, importance, and cascade layers can resolve a conflict before specificity is considered. Scope proximity and then source order can break a tie. Inline styles, !important, browser support, whether a selector matches an element, and stylesheet context need separate inspection. Expand nested selectors against their parents before entering them.

What to know

  • At most 100 selectors and 20,000 characters.
  • No full cascade evaluation, nesting expansion, or element matching.

Common questions

Why do commas inside :is() stay in one row?

A comma inside a functional pseudo-class is part of its argument list. Only top-level commas split comparison rows; commas inside attribute strings are also preserved.

Does :hover count as a class?

For specificity, a normal pseudo-class such as :hover belongs in the B column alongside class and attribute selectors. Pseudo-elements such as ::before belong in C.

Can I paste an entire stylesheet?

No. Enter selectors only. Declaration blocks, !important, and nested & selectors require their surrounding stylesheet context and are outside this comparison.

Sources & references