Skip to main content

CSS Specificity Calculator — Score, Compare, and See Why a Selector Wins

Score any CSS selector as an (a, b, c) triple, compare which rule wins the cascade, and see exactly which digit decided it — browser-only

  • Runs locally
  • Category Developer & DevOps
  • Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
Specificity
#nav .item a
(1, 1, 1)Wins the cascade
Breakdown
#nava.itembac
ul li.active
(0, 1, 2)
Breakdown
ulclic.activeb
:is(.promo, #hero) span
(1, 0, 1)
Breakdown
:is(.promo, #hero)aspanc
.btn.btn
(0, 2, 0)
Breakdown
.btnb.btnb
Compared left-to-right: 1,1,1 > 1,0,1 — decided at b (1 vs 0)
a = IDsb = classes / attributes / pseudo-classesc = elements / pseudo-elements

How to raise / lower specificity

  • Lower it: wrap the selector in :where() — `:where(#sidebar) .link` scores (0,1,0) instead of (1,1,0). Great for resettable design-system defaults.
  • Lower it: drop the ID and target a class or data-attribute instead — `[data-nav] a` (0,1,1) is far easier to override than `#nav a` (1,0,1).
  • Raise it: chain the selector to itself — `.btn.btn` scores (0,2,0) and beats a single `.btn` without touching the HTML or adding !important.
  • Raise it: add an attribute selector you know is present — `a[href]` (0,1,1) outranks plain `a` (0,0,1) while still matching the same elements.
  • Last resort: !important wins regardless of the triple, but two competing !important rules fall back to normal specificity, then source order. Reserve it for utility overrides, never as a default.

What this tool does

Paste one or more CSS selectors and get the specificity triple (a, b, c) for each in real time — a = IDs, b = classes / attributes / pseudo-classes, c = elements / pseudo-elements. It handles the parts people get wrong: :is() and :not() take their most specific argument, :where() always scores zero, ::before is an element, [attr] counts as a class, the universal selector and combinators count for nothing, and !important is flagged separately because it sits outside the triple. Drop in several selectors and the tool highlights which one wins the cascade and explains the decisive a > b > c digit. 100% client-side.

Tool details

Input
Text + Structured content
The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
Output
Live result + Copy
The result area focuses on usable output, with copy, download, or preview actions when supported.
Privacy
Browser-side processing
The main tool logic does not call an external API, so inputs normally stay in the current tab.
Save / share
Shareable URL state
Key settings are encoded in the URL so another person can reopen the same setup.
Performance budget
Initial JS <= 9 KB
No WASM budget is declared, keeping the tool quick to open on mobile.
Best fit
Developer & DevOps · Developer
Category and role tags drive related tools, internal links, and quick fit checks.

How to use

  1. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 3. Copy / Download

    Copy the result or download to disk in one click.

How CSS Specificity Calculator fits into your work

Use it in the small gaps between coding, reviewing, debugging, and shipping.

Developer jobs

  • Formatting, validating, shrinking, or inspecting code-adjacent text.
  • Preparing snippets for documentation, tickets, commits, or handoff.
  • Checking a small payload quickly without switching tools.

Developer checks

  • Run irreversible transforms like minify or obfuscate on a copy.
  • Keep secrets out of pasted snippets unless the tool explicitly stays local.
  • Use your normal tests or linter before shipping transformed code.

Good next steps

These links move the current task into a more complete workflow.

  1. 1 CSS Formatter & Minifier Format and beautify CSS — sort properties, indent rules, expand or minify. Open
  2. 2 Regex Tester Test JavaScript regex live — match highlighting, group capture, replace preview, flag toggles — browser-only Open
  3. 3 CSS Minifier Minify CSS — strip comments, whitespace, shorten colors, merge selectors. 30-60% smaller. Open

Real-world use cases

  • Settle a "why isn't my style applying" bug in code review

    A teammate's `#sidebar .link { color: red }` keeps winning over the new `.link--muted { color: gray }` and nobody can say why on sight. Paste both selectors, one per line. The tool scores them (1,1,0) vs (0,1,0) and highlights the ID rule as the winner, with a note that the a column (1 vs 0) decided it. Now the fix is obvious: either raise the muted rule's a column, or — better — wrap the sidebar's `#sidebar` in `:where()` so it drops to (0,1,0) and stops bullying every later override. Two pasted lines end the argument faster than opening dev tools.

  • Audit a design system for over-specific defaults

    You're shipping a component library and want every base style to be trivially overridable by consumers. Paste your base selectors in a batch — `.card`, `.card .title`, `#app .card`, `nav ul li a`. Any row scoring above (0,1,0) is a future support ticket: a consumer who can't override it without copying your specificity. Rewrite the heavy ones with `:where()` (e.g. `:where(nav) ul li a` → (0,0,3) instead of (0,0,4) plus structural weight) and re-paste to confirm the triples dropped.

  • Decide between :is() and :where() before refactoring

    You're collapsing five near-identical rules into one with `:is()` to cut bytes, but you're not sure if it'll change which declarations win. Paste the original `.menu .a, .menu .b, .menu .c` and the proposed `.menu :is(.a, .b, .c)` and compare the triples side by side — both land at (0,2,0), so the refactor is specificity-neutral and safe to ship. If you'd reached for `:where()` instead, the tool would show the drop to (0,1,0) and warn you the rule just got weaker.

  • Teach a junior dev the cascade with a shareable link

    Explaining specificity over Slack is painful. Type a few contrasting selectors, let the URL capture them, and paste the share link. The recipient opens the exact same comparison — `#id` beating `.a.b.c.d.e`, `::before` only adding to the c column, `:where()` zeroing an ID — with the per-token breakdown already rendered. It's a live worked example instead of a wall of theory, and they can edit the selectors to test their own hunches.

  • Predict the winner before adding !important

    Before you reach for `!important` to force a style, paste the rule that's currently winning and your new rule. If your new rule's triple is already higher, you don't need `!important` at all — you needed a more specific selector, which the tool will confirm. If they're tied, the tool tells you source order decides, so moving your rule later in the stylesheet fixes it cleanly. Reserve `!important` for the genuine cases where you've confirmed a lower triple can't be raised.

Common pitfalls

  • Counting `:where()` as if it added weight. `:where(#nav) .link` is (0,1,0), not (1,1,0) — the entire `:where()` argument contributes zero. If you treat it like `:is()` you'll predict the wrong winner. Read the breakdown chip: the `:where()` token is labelled "always 0".

  • Putting `::before` in the b column because it starts with a colon. Pseudo-elements (`::before`, `::after`, `::first-line`) add to c (the element column), not b. Only pseudo-classes (`:hover`, `:nth-child()`) go in b. The double colon is the tell.

  • Assuming combinators add weight. `div > p + span` is (0,0,3) — the `>` and `+` count for nothing, only the three element names do. Same for the descendant space and `~`. They affect *what matches*, never *how specific*.

  • Treating a big b column as able to overflow into a. Specificity never carries between columns. `.a.b.c…` ×100 is still (0,100,0) and loses to any single `#id` at (1,0,0). There is no base-256 rollover in any current engine.

Privacy

The whole calculator is a JavaScript tokenizer that runs in your browser tab — selectors are split, classified into the (a, b, c) columns, and ranked entirely on the page. Nothing is parsed on a server, and there's no logging of which selectors you tested. The one caveat: the shareable URL encodes your selectors in the query string (`?sel=...`), so a share link pasted into Slack or email leaves those selectors in the destination's access log. CSS selectors are rarely sensitive, but if a selector reveals an unreleased component name or internal ID scheme you'd rather not log, copy the result manually instead of sharing the URL.

FAQ

Tool combos

Folks in your role tend to reach for these alongside this tool.

Made by Toolora · 100% client-side · Updated 2026-06-13