UseToolSuite UseToolSuite

CSS Specificity Calculator

Calculate and compare CSS selector specificity scores. Visual breakdown of ID, class, and element weights to debug cascade conflicts fast.

One per line or comma-separated
Try:

Enter CSS selectors above to calculate specificity

Click an example button to get started

Specificity Legend

A

ID selectors

#id
B

Classes, attributes, pseudo-classes

.class [attr] :hover
C

Elements, pseudo-elements

div ::before

How Specificity Works

Specificity is compared component by component from left to right: A (IDs) is compared first, then B (classes), then C (elements). A single ID selector (1,0,0) always beats any number of class selectors (0,n,0). The universal selector (*), combinators (+, >, ~, space), and :where() have zero specificity. The :not(), :is(), and :has() pseudo-classes take the specificity of their most specific argument. Inline styles override all selector-based specificity, and !important overrides inline styles.

How specificity is scored

Every selector gets a three-part score (A, B, C), compared left to right — a higher left column always beats any amount of the columns to its right:

ColumnCountsExample
A (IDs)#id selectors#nav
B (classes).class, [attr], :hover.active, :focus
C (elements)div, ::beforea, li

So #nav a (1,0,1) beats div.container ul li a (0,1,4) — one ID outranks four classes/elements combined. This is why ID-based styling is a trap: once you’ve used an ID, every override needs an ID too, and your specificity ratchets upward.

The pseudo-class twist

The newer functional pseudo-classes have specific, sometimes surprising weights:

  • :not(), :is(), :has() add zero themselves but take the specificity of their most specific argument:is(#id, .class) scores as an ID.
  • :where() is the escape hatch: it always contributes zero specificity, no matter its arguments. Perfect for low-priority defaults you want to be trivially overridable.

Beyond specificity: the full cascade order

Specificity is only one tiebreaker. When the browser resolves competing rules, it considers, in order: origin and importance (is it !important? author vs user-agent?), then cascade layers (@layer), then specificity, then source order. Cascade layers (see FAQ) sit above specificity, which is what makes them so useful — they let a low-specificity rule in a high layer beat a high-specificity rule in a low layer. Inline style="…" outranks selector rules entirely, and only !important can override an inline style.

Debugging a rule that won’t apply

When a style isn’t taking effect, it’s almost always being overridden by something with higher precedence. Paste both selectors into this calculator to compare scores: if one is higher, that’s your answer; if they’re equal, the later one in the stylesheet wins, so check source order; if neither explains it, look for an !important, an inline style, or a cascade layer changing the outcome.

is compiled away. */}

Last updated

How helpful was this tool?

Click to rate

Embed this tool on your site

Paste this snippet into any HTML page or blog post to embed a live, fully working copy of CSS Specificity Calculator. Free for any use.

Key Concepts

Cascade

The CSS cascade is the algorithm that resolves conflicts between multiple CSS rules targeting the same element. It considers (in order): importance (!important), specificity, source order, and origin (user agent, author, user stylesheets).

Selector Weight

Another term for specificity — the calculated priority of a CSS selector. Higher weight means the rule takes precedence when multiple rules compete for the same property on the same element.

Frequently Asked Questions

What is CSS specificity?

CSS specificity is a scoring system browsers use to decide which CSS rule applies when multiple rules target the same element. It is expressed as three numbers (A, B, C): A counts ID selectors (#id), B counts class selectors (.class), attribute selectors ([attr]), and pseudo-classes (:hover), and C counts element selectors (div) and pseudo-elements (::before). Higher numbers win, compared left to right.

Does the order of selectors matter?

When two selectors have equal specificity, the one that appears later in the stylesheet wins (source order). However, specificity always takes priority over source order — a more specific selector will win even if it appears earlier in the CSS file.

How does !important affect specificity?

!important overrides all specificity calculations. However, if two rules both use !important, normal specificity comparison applies between them. Overusing !important leads to unmaintainable CSS — it is better to increase specificity intentionally or restructure your selectors.

What is the specificity of :not(), :is(), and :has()?

The :not(), :is(), and :has() pseudo-classes themselves add zero specificity. Instead, they take the specificity of their most specific argument. For example, :not(.active) has the same specificity as .active → (0,1,0). The :where() pseudo-class is unique — it always has zero specificity regardless of its arguments.

How do inline styles compare to selectors?

Inline styles (style="...") have a specificity that beats any selector-based rule. The only way to override an inline style with a stylesheet rule is to use !important. In specificity notation, inline styles are sometimes represented as (1,0,0,0) — a fourth component that outranks all selector specificity.

How do I keep specificity low and avoid !important wars?

The goal is FLAT specificity — most rules at roughly the same low weight — so the cascade is decided by source order, which is predictable, instead of by escalating selectors. Practical tactics: prefer a single class per rule (.card-title, not header.main .card h2); avoid IDs for styling (an ID jumps you to a high column you'll have to out-specify forever); wrap selectors in :where() when you want them to match but contribute ZERO specificity, which is great for resets and defaults that should be easy to override; and lean on a methodology like BEM that names components with classes. When you find yourself reaching for !important to win, that's the signal your specificity is already too tangled — flatten the selectors instead. !important should be a last resort (or reserved for utility overrides), not a routine tool.

What are CSS cascade layers (@layer) and how do they change specificity?

@layer lets you group CSS into ordered layers, and the layer order beats specificity entirely between layers. You declare an order — @layer reset, base, components, utilities — and a rule in a LATER layer wins over a rule in an earlier layer even if the earlier rule has higher specificity. This is transformative for managing large codebases and third-party CSS: you can put a framework in a low-priority layer and your overrides in a higher one, so your simple .button class reliably beats the framework's .nav ul li a without a specificity arms race. Within a single layer, normal specificity and source order still apply. Cascade layers are supported in all current major browsers and are the modern way to make 'which rule wins' intentional rather than accidental.

Troubleshooting & Technical Tips

A style is not being applied even though the selector matches

The most likely cause is that another rule with higher specificity is overriding it. Paste both selectors into this calculator to compare their specificity scores. If they are equal, check source order — the later rule wins. Also check for !important declarations that override specificity.

Understanding why a long selector beats a short one

A selector like "div.container ul li a" (0,1,4) has lower specificity than "#nav a" (1,0,1) because a single ID selector always outweighs any number of class and element selectors. The number of components matters less than which column they fall in.

Related Tools