Skip to content

CSS Specificity Calculator

Paste one or more CSS selectors, comma-separated, and get the real (A, B, C) specificity triple for each — IDs, then classes/attributes/pseudo-classes, then elements/pseudo-elements — including correct handling of :not(), :is(), :has() and :where(), which most naive calculators get wrong.

  • Correct (A, B, C) triple per selector, not a fake single score
  • :not()/:is()/:has() take the specificity of their most specific argument
  • :where() always contributes zero
  • Comma-separated selector lists, split correctly around nested parens
  • Runs fully client-side

Calculator

Calculated locally, nothing uploaded

Enter a selector to see its specificity.

How to calculate CSS specificity

  1. 01

    Paste a selector

    Or several, separated by commas — each is scored independently.

  2. 02

    Read the triple

    The three numbers are ID count, class/attribute/pseudo-class count, and element/pseudo-element count, in that priority order.

Why this shows a triple instead of one number#

CSS specificity is not a single number — it is a three-column comparison, checked left to right: any selector with even one more ID wins outright, no matter how many classes or elements the other side has. Only when the ID count ties does the class/attribute/pseudo-class column get compared, and only when that ties too does the element count matter. Collapsing this into a single number (some calculators do this by treating the columns as digits in one base) can misrepresent close cases, so this tool shows the real triple and compares column by column, matching how browsers actually resolve the cascade.

Why :not(), :is() and :has() need special handling#

A naive calculator counts :not(...) as one pseudo-class, contributing a flat +1 to the class column regardless of what's inside — which is wrong. The actual CSS spec says these functional pseudo-classes contribute the specificity of their most specific argument, not a flat count. #id:not(.foo) scores as (1, 1, 0) — the 1 in the ID column comes from #id, and the 1 in the class column comes from what :not() actually contains (.foo), not from :not() itself. This tool implements that rule, recursively, including for a comma-separated argument list where the most specific branch is what counts.

Why :where() is the odd one out#

:where() is defined to always contribute zero specificity, no matter what selector is inside it — this is the entire reason it exists as a separate pseudo-class from :is(), which behaves like :not() and does count its contents. :where(.a, #b) contributes nothing at all to the specificity, which makes it useful specifically for writing overridable default styles.

Frequently asked questions

Why three numbers instead of one specificity score?

Because specificity comparison is column by column, not one merged number — a single extra ID always outweighs any number of classes, and a single extra class always outweighs any number of elements. Showing the real triple matches how browsers actually compare selectors.

Does :not(.foo) count as one point, like a normal pseudo-class?

No — per the CSS spec, :not(), :is() and :has() contribute the specificity of their most specific argument, not a flat +1. #id:not(.foo) scores (1, 1, 0): the class point comes from .foo inside the parentheses, not from :not() itself.

Why does :where() never add anything?

:where() is specifically defined to always contribute zero specificity, regardless of its contents — that is its entire purpose, distinguishing it from :is(), which does count.

Is my CSS sent anywhere?

No. The calculation runs entirely in your browser.

Developers

UUID Generator

Generate cryptographically random UUID v4 or time-ordered UUID v7, in bulk.

Developers

Base64 Encoder & Decoder

Encode and decode Base64 with correct UTF-8 handling, including the URL-safe alphabet.

Developers

ULID Generator

Generate ULIDs — sortable by creation time like UUID v7, but Crockford Base32 instead of hex.