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.