CSS Specificity Calculator — Compute Any Selector's (a, b, c) Score
Paste any CSS selector and instantly get its specificity as (a, b, c) per CSS Selectors Level 4. Handles :is(), :not(), :has(),:where(), attribute selectors, pseudo-elements, and combinators correctly. Compare two selectors side-by-side to settle which rule wins the cascade. Free, no signup, 100% in your browser.
IDs (a)
0
Classes (b)
3
Elements (c)
0
Breakdown
Selectors Level 4 Spec
Returns specificity as (a, b, c) triple per the modern CSS Selectors Level 4 spec. Correctly handles :is(), :not(), :has() (max of args), and :where() (always 0).
Compare Mode
Paste two selectors and the tool names the winner and the deciding column (a, b, or c). Settles "why is the wrong rule applying" bugs in seconds.
Token Breakdown
Each part of the selector is colored and labeled (ID / class / attribute / pseudo-class / pseudo-element / element / combinator) so you see exactly where the weight comes from.
100% Client-Side
All parsing runs in your browser via custom JavaScript — no fetch, no signup. Works offline once loaded.
CSS Specificity Calculator: Compute Any Selector's (a, b, c) Score
A CSS specificity calculator tells you which rule wins the cascade by scoring a selector as a triple (a, b, c): a = ID selectors, b = class, attribute, and pseudo-class selectors, c = element and pseudo-element selectors. Paste a selector and this tool returns its score per CSS Selectors Level 4, with a per-token breakdown and a compare mode that settles which of two rules wins. It runs 100% in your browser, free.
How to calculate CSS specificity
- Paste a selector such as
main #content .card .button:hoverinto the input — the score updates as you type. - Read the
(a, b, c)result and the colored token breakdown showing where each point comes from (ID, class, attribute, pseudo-class, pseudo-element, element, combinator). - Open Compare mode and paste a second selector to see which of two competing rules wins, and by which column.
- Load a sample selector (10 are pre-built, covering
:is(),:where(), attribute, and pseudo-element cases) to learn the rules fast. - To lower a score, swap an ID for a class or wrap part of the selector in
:where(), then re-check the new(a, b, c).
How specificity decides which rule wins
Browsers compare the three columns left to right, not as one number. A selector with a higher a beats any selector with a lower a, regardless of b and c. Only when a ties do they compare b, then c. If all three tie, the rule that appears later in the source wins. The exact algorithm is defined in the MDN Specificity reference and the W3C Selectors Level 4 specification, which every major browser conforms to.
Combinators (>, +, ~, and the descendant space) add nothing to the score; they only change which elements match. The universal selector * also adds zero. Three functional pseudo-classes are special: :is(), :not(), and :has() take the maximum specificity of their arguments, while :where() always counts as (0, 0, 0) no matter what it wraps.
Worked examples: selector → score
#main .card → (1, 1, 0)
One ID and one class. This beats any rule made only of classes and elements, however long.
header nav ul li a → (0, 0, 5)
Five element names, zero classes. A single class rule .link at (0, 1, 0) outranks it outright.
.row :is(h1, h2, .title) → (0, 2, 0)
The descendant .row adds one class; :is() takes the max of its arguments, and .title (one class) outweighs h1, adding a second class. Swap :is for :where and the wrapper contributes zero, dropping the whole selector to (0, 1, 0) — just .row.
Edge case · :not() inflates more than you expect
p:not(.intro):not(.footer) scores (0, 2, 1), not (0, 0, 1). The :not() pseudo-class itself is free, but it inherits the max specificity of its argument — each .intro and .footer adds one class. Two negations means two classes.
Pair this with the CSS Beautifier to read the stylesheet you are debugging, the CSS Minifier to compress it for production, and the Color Contrast Checker to verify accessibility once the cascade resolves.
CSS Specificity Rules — What Counts & What Does Not
| Selector Part | Weight Added | Notes |
|---|---|---|
| Inline style (style attribute) | (1, 0, 0, 0) — beats every selector | Per spec, inline style is a separate dimension above selectors. CSS-in-JS often emits it. |
| ID selector (#id) | adds 1 to "a" | IDs are heavy — avoid using them in stylesheets when classes will do. |
| Class (.cls) | adds 1 to "b" | Workhorse selector. Stack two classes (.btn.btn) to outweigh a single class without raising ID count. |
| Attribute ([type="text"]) | adds 1 to "b" | Same weight as a class — useful for form-state styling without classes. |
| Pseudo-class (:hover, :focus) | adds 1 to "b" | Includes :is(), :has() which inherit max specificity of arguments. |
| Element (div, span) | adds 1 to "c" | Lightest — most selectors involve at least one element name. |
| Pseudo-element (::before) | adds 1 to "c" | Same weight as element. Double-colon syntax is modern; single-colon is legacy alias. |
| * universal selector | adds 0 to all | Pure noise for specificity — only useful for cascading effects. |
| Combinators (>, +, ~, space) | 0 | Direction/relationship, not weight. Do not affect specificity. |
| :where(X) — special | 0 | Argument specificity is DISCARDED. Use :where to opt out of specificity wars. |
| :is(X) / :not(X) / :has(X) | takes MAX of argument specificity | Lets you express alternatives without inflating beyond the heaviest alternative. |
Five Common Specificity Problems & Fixes
1. Style not applying
Compute specificity of the rule you want vs the rule that won. Whichever has higher (a, b, c) wins. Bump yours by adding a class, NOT an ID.
2. Two rules with same specificity
CSS uses source order: whichever appears LATER in the stylesheet wins. Reorder or use a more specific selector.
3. !important war
Avoid !important except for utility classes (e.g. .hidden { display: none !important }). One !important beats specificity; two !importants compete by specificity.
4. Inline style wins everything
Inline style="..." beats every stylesheet selector except !important. Move to a class-based rule or use :is() to lift cascade weight.
5. Component styles stomping app
Wrap library/component styles in :where(.lib) — specificity contributes 0, so app rules always win.
Four Specificity Best Practices for 2026
1. Keep Specificity Flat
Aim for (0, 1, 0) or (0, 2, 0) for most rules — one or two classes. Component-driven CSS pairs naturally with low-specificity selectors that compose cleanly.
2. Avoid IDs in Stylesheets
ID selectors are heavy and locked to single elements. Use classes for styling, reserve IDs for JS hooks and accessibility relationships (aria-labelledby).
3. Use :where() for Library Styles
Component libraries should wrap their CSS in :where(.lib) so application code can override with a single class. Modern CSS-in-JS libraries embrace this pattern.
4. !important Is a Last Resort
Use !important only for utility classes that MUST win (e.g. .visually-hidden). For everything else, raise the specificity slightly with an additional class — never via ID, never via !important.
The "256 classes beat an ID" myth, settled
You may have read that 256 chained classes (.a.a.a…) overflow into the ID column and beat a single #id. That was a real bug in old IE, Gecko, and WebKit builds, where each column was stored in an 8-bit field that wrapped at 256. It is not the spec, and no current browser does it. The spec uses a number system with a base large enough that the columns never carry — so (0, 256, 0) still loses to (1, 0, 0). Treat each column as a separate tier, never as a decimal score.
One thing to know about this calculator: it shows an internal "score" only to size the comparison bars and sort results — it deliberately weights columns as a×10000 + b×100 + c. That packed number is for the UI alone and would misrank pathological selectors with 100+ classes. The win/lose verdict and the (a, b, c) readout always use true column-by-column comparison, exactly as browsers do.
Runs 100% in your browser
Your selectors never leave your device. Parsing happens locally in JavaScript with no network request, so the tool works offline once the page loads — no uploads, nothing leaves your device. I tested it against the tricky cases that trip up most calculators: input[type="text"]:focus, nested :not() chains, :nth-child(2n+1 of .row), double-colon versus legacy single-colon pseudo-elements, and the universal selector. Each result matches what Chrome and Firefox DevTools report for the same rule.
Related CSS & styling tools
Format the stylesheet before debugging specificity
CSS MinifierCompress your CSS for production
CSS Filter GeneratorBuild blur, brightness & contrast filters
CSS Gradient GeneratorCreate linear & radial gradient code
CSS Clip-Path GeneratorCut shapes with the clip-path property
Border Radius GeneratorRound corners with live preview
Flexbox GeneratorVisual one-dimensional layout playground
Grid GeneratorBuild two-dimensional CSS grid layouts
Box Shadow GeneratorLayer and export box-shadow code
Color ConverterConvert HEX, RGB, HSL & OKLCH values
Color Contrast CheckerVerify WCAG 4.5:1 contrast once styles resolve
Glassmorphism GeneratorFrosted-glass backdrop-filter effects
Last updated: June 2, 2026 · Runs 100% in your browser — no uploads, nothing leaves your device.
Need a different tool?
Browse all 89 free, in-browser tools — or tell us what we should build next.