CSS Specificity Calculator
Score one or many CSS selectors live as you type. Each gets its spec-accurate (a,b,c) tuple - IDs, classes/attributes/pseudo-classes, and elements/pseudo-elements - with a per-token breakdown showing exactly which piece feeds which column. It handles :is(), :where() (which contributes zero), and :not() correctly, flags !important and inline styles as higher precedence, then ranks every selector and shows which one wins (or ties). Copy or share a full report.
About this ToolHow it works, benefits & use casesTap to collapse
When two CSS rules fight over the same element, specificity decides the winner - and this calculator scores every selector you type, live, the moment you type it. Enter one selector per line and each gets its spec-accurate three-part (a,b,c) tuple: a counts IDs, b counts classes, attribute selectors and pseudo-classes, and c counts elements and pseudo-elements. Every selector is broken down token by token, with colored chips showing exactly which piece feeds which column, so you can see at a glance why one rule outweighs another. It handles modern selectors correctly: :where() always contributes zero, while :is() and :not() take the specificity of their most specific argument. It also flags !important and inline styles, which sit above the tuple entirely in the cascade. All your selectors are then ranked from highest to lowest precedence, the winner is highlighted, and genuine ties are called out so you know source order will break them. A set of canonical reference examples - pre-scored with their tuples - is one click away, and you can copy or share a full plain-text report. Everything runs locally in your browser and the input is captured in a shareable URL.
How to Use
- 1Type or paste CSS selectors into the input, one per line - the ranking recalculates on every keystroke.
- 2Read each selector's (a,b,c) tuple and the colored token chips showing which piece feeds which column.
- 3Check the ranked list to see which selector wins, or whether several tie for the top.
- 4Click a reference example to append it and watch how its specificity breaks down.
- 5Copy, download, or share the full report with a teammate.
Key Benefits
- Live, keystroke-by-keystroke scoring of many selectors at once - no run button
- Spec-accurate (a,b,c) tuples with a per-token breakdown highlighting each contribution
- Correct handling of :is(), :where() (which scores zero), and :not()
- Detects and flags !important and inline styles as higher precedence
- Ranks all selectors highest to lowest and clearly marks the winner (and ties)
- Curated, pre-scored reference examples from trivial to deliberately complex
- Copyable, shareable report and a URL that captures the exact input
Common Use Cases
- Debugging why one rule overrides another in a stylesheet
- Comparing several competing selectors at once before editing
- Deciding whether to add an ID or refactor to keep specificity low
- Teaching how the CSS cascade weighs IDs, classes, and elements
- Auditing legacy CSS where overly specific selectors cause conflicts
#header .nav li a:hover wins with the highest precedence (1,2,2).
#header .nav li a:hover1,2,2#header.navlia:hover:is(#main, .content) p1,0,1:is(#main, .content)p.nav a0,1,1.navaul li a0,0,3ullia
Copy, download, or share the full ranking
CSS Specificity Report
======================
Notation: (a,b,c) = (IDs, classes/attributes/pseudo-classes, elements/pseudo-elements)
Ranked highest -> lowest precedence:
1. (1,2,2) #header .nav li a:hover <- winner
2. (1,0,1) :is(#main, .content) p
3. (0,1,1) .nav a
4. (0,0,3) ul li a
Per-selector breakdown:
#header .nav li a:hover -> (1,2,2)
- #header -> a (ID) [ID]
- .nav -> b (class/attr/pseudo) [class]
- li -> c (element/pseudo-el) [element]
- a -> c (element/pseudo-el) [element]
- :hover -> b (class/attr/pseudo) [pseudo-class]
:is(#main, .content) p -> (1,0,1)
- p -> c (element/pseudo-el) [element]
.nav a -> (0,1,1)
- .nav -> b (class/attr/pseudo) [class]
- a -> c (element/pseudo-el) [element]
ul li a -> (0,0,3)
- ul -> c (element/pseudo-el) [element]
- li -> c (element/pseudo-el) [element]
- a -> c (element/pseudo-el) [element]
Result: "#header .nav li a:hover" wins with the highest precedence.One selector per line — specificity updates live
Reference examples
Click any example to append it to the input and see how it scores.
How specificity is scored
Each selector gets a three-part (a,b,c) tuple. The a column counts IDs, b counts classes, attribute selectors and pseudo-classes, and c counts elements and pseudo-elements. Columns are compared left to right, so a single ID always beats any number of classes.
:is(), :where() and :not()
:where() always contributes zero, which makes it perfect for low specificity resets. :is() and :not() take the specificity of their most specific argument. !important and inline styles sit above the tuple entirely and are flagged as such.
Was this tool helpful?
Share Your Experience
Help others discover this tool!
Related tools
- Sitemap Priority CalculatorPaste a list of URLs and get a complete XML sitemap with priorities from a transparent, tunable model — each URL auto-classified by type & depth, with a per-row score breakdown and priority distribution analysis
- CSS FormatterFormat and beautify CSS code
- CSS MinifierMinify CSS code
- Parallax Effect CalculatorBuild multi-layer parallax with pure-CSS perspective, JS scroll, or React — scrollable live preview
- Unused CSS DetectorFind CSS selectors never matched by your HTML, see how many bytes you can save, and get cleaned CSS - with a safelist for dynamic classes
- View Transitions CSS GeneratorGenerate cross-document @view-transition CSS and the startViewTransition() JS path — with a live preview
Each selector gets a three-part (a,b,c) tuple. The a column counts IDs, the b column counts classes, attribute selectors and pseudo-classes, and the c column counts elements (type selectors) and pseudo-elements. The columns are compared left to right, so a single ID always beats any number of classes, and any class beats any number of elements. Inline styles and !important sit above the tuple entirely and are flagged separately.
The CSS specification defines :where() as a zero-specificity pseudo-class: whatever you put inside it, it adds nothing to the score. That makes it ideal for low-specificity resets and defaults that are easy to override later. By contrast, :is() and :not() take the specificity of their most specific argument, so :is(#id, .class) scores like the #id.

