How to use it
- Type a selector into Selector, written as it is in your stylesheet.
- Type a second selector into Second selector (optional) to compare the two, or leave it empty.
- Read Specificity (a, b, c) for the first selector, and Which rule wins when you gave two.
- Use the Parts counted table to see which part of each selector gave each number.
How the three numbers are counted
The Selectors Level 3 Recommendation counts a selector in three columns. The tool compares the numbers from left to right: a first, then b, then c. The universal selector * and the combinators such as > and + are ignored.
- a is the number of ID selectors, such as #nav.
- b is the number of class selectors such as .active, attribute selectors such as [href], and pseudo-classes such as :hover.
- c is the number of type selectors such as li or a, and of pseudo-elements such as ::before.
Pseudo-classes with arguments
:is(), :not() and :has() count as their most specific argument, so :is(#a, .b) is (1, 0, 0). :where() counts for nothing. :nth-child() counts as one pseudo-class plus the most specific selector in its "of S" list, so :nth-child(even of li, .item) is (0, 2, 0). These rules come from the Selectors Level 4 draft, which is an Editor's Draft and may change.
What the tool does not do
- It counts a pseudo-element with arguments, such as ::part(x), as one pseudo-element, and does not read its argument.
- It does not read nesting with &, and it takes one selector per box, not a list with commas.
- It cannot see your stylesheet, so when two selectors tie it says that the later rule wins and leaves the order to you.
Worked example: a link in a navigation bar
The first selector, #nav li.active > a:hover, has one ID, #nav. It has two classes and pseudo-classes, .active and :hover, and two types, li and a. Its specificity is (1, 2, 2). The second selector, #nav a, has one ID and one type, so its specificity is (1, 0, 1). The first selector wins, because a is equal and b and c are higher.
| Selector | a | b | c |
|---|---|---|---|
| #nav li.active > a:hover | 1 | 2 | 2 |
| #nav a | 1 | 0 | 1 |
Frequently asked questions
Why does an ID count in the first column?
The tool compares the columns from left to right, so the ID column a is decided first. A selector with one more ID has a higher a, and the classes and types in b and c are not looked at in that case.
Does the order of the rules matter?
Only when two selectors have the same specificity. The CSS Cascade Level 4 specification says the last declaration in document order wins at that point, so the later rule takes effect.
Why does :not(#a) add to the specificity?
The :not() pseudo-class itself is not counted, but its argument is. The Selectors Level 3 example #s12:not(FOO) is (1, 0, 1): one ID from #s12, and one type from the argument FOO.
Do the universal selector and the combinators add anything?
No. The universal selector is ignored, and so are the combinators such as >, + and ~. The example * in the Level 3 section has the specificity (0, 0, 0).
Does this tool include inline styles and !important?
No. It counts one selector. The cascade compares origin and importance before specificity, so a rule marked !important or an inline style can win whatever the selectors score. Compare only two selectors that set the same property with the same importance.
Is the selector I type sent anywhere?
No. The parsing runs in your browser, and nothing you type is stored or sent to our server. Check the result before you change a stylesheet.
Sources
- W3C: Selectors Level 3, Calculating a selector's specificity
- W3C: Selectors Level 4 (Editor's Draft), specificity rules
- W3C: CSS Cascade Level 4, cascade sorting order
Figures and text last checked on Thursday, November 12, 2026.