Figure out CSS specificity in seconds.
Paste any CSS selector and see its (a, b, c) score, a token-by-token breakdown of every contributing part, and a plain-English explanation. Compare two selectors to find out which one wins and why.
Paste your selector
Type or pick a preset example to start
See the score instantly
ID, class, and type counts update as you type
Compare to find the winner
Switch to compare mode for two conflicting selectors
Specificity quick reference
| Selector type | Example | Score |
|---|---|---|
| Inline style | style="color:red" | (1, 0, 0) |
| ID | #header | (1, 0, 0) |
| Class | .button | (0, 1, 0) |
| Attribute | [type="text"] | (0, 1, 0) |
| Pseudo-class | :hover, :nth-child(2) | (0, 1, 0) |
| Type selector | div, p, a | (0, 0, 1) |
| Pseudo-element | ::before, ::after | (0, 0, 1) |
| Universal | * | (0, 0, 0) |
| :where() | :where(.nav) | (0, 0, 0) |
| :not() / :is() / :has() | :not(.active) | argument's score |
| !important | color: red !important | Overrides cascade |
Combinators > + ~ and whitespace contribute zero specificity and are ignored in the calculation.
Common specificity problems and fixes
My class won't override a component's ID style
#id beats .classIDs always beat classes — no number of classes can win. Refactor: remove the ID selector from your stylesheet and use a class instead. Or wrap the component in :where(#id) to strip the ID's specificity to zero.
I'm using !important everywhere and it's escalating
Specificity creepYou're in a specificity war. Use CSS @layer to establish a clear priority order: wrap library styles in one layer and your overrides in another. Your layer always wins without any !important.
I can't override a third-party library's styles
Library overridesWrap the library import in a @layer: @layer library { @import 'lib.css'; } — then write your overrides outside any layer. Un-layered CSS always beats layered CSS.
I need base styles that are always easy to override
Design system resetsUse :where() to write base styles at zero specificity: :where(h1, h2, h3) { margin: 0; }. Any single class override will beat it without needing !important.
Frequently Asked Questions
What is CSS specificity?
CSS specificity is a three-number score (a, b, c) that determines which CSS rule wins when two rules target the same element. Selectors are compared left to right — column A always beats column B.
| Column | What counts | Example | Score |
|---|---|---|---|
| a | ID selectors | #header | (1, 0, 0) |
| b | Class, attribute, pseudo-class | .btn, [type], :hover | (0, 1, 0) |
| c | Type selectors, pseudo-elements | div, p, ::before | (0, 0, 1) |
How do I calculate CSS specificity by hand?
Count each part separately: IDs → column A, classes/attributes/pseudo-classes → column B, types/pseudo-elements → column C.
/* nav > ul li.active:hover — step by step */
nav /* type → (0, 0, 1) */
ul /* type → (0, 0, 1) */
li /* type → (0, 0, 1) */
.active /* class → (0, 1, 0) */
:hover /* pseudo → (0, 1, 0) */
/* > + ~ space — combinators ignored */
/* Total: (0, 2, 3) */Does !important affect specificity?
!important does not change the specificity score — it bypasses the cascade entirely, regardless of score.
- A rule marked
!importantwins over any non-!importantrule, even one with a higher score. - Two competing
!importantrules fall back to comparing specificity normally. - Avoid
!importantin application CSS — it can only be overridden by more!importantrules, causing escalating stylesheet debt.
What is :where() and why does it have zero specificity?
:where() applies styles based on its argument selector but contributes zero specificity — (0, 0, 0) — regardless of how complex the argument is.
/* Zero specificity — any single class can override */
:where(h1, h2, h3) { margin: 0; }
/* This wins without !important */
.custom-title { margin: 1.5rem; }Can 100 class selectors ever beat 1 ID selector?
No. The columns (a, b, c) are compared left to right and never overflow into each other.
| #header (1 ID) | .a.b.c × 100 classes | |
|---|---|---|
| Score | (1, 0, 0) | (0, 100, 0) |
| Column A | 1 | 0 |
| Winner? | Yes — column A decides | No — loses on column A |
To avoid this trap: don't use ID selectors in stylesheets. Use classes and :where() instead.