Xerobit

CSS Specificity Calculator: Compute and Compare Selectors

Enter one or more CSS selectors to compute their specificity as an (a, b, c) tuple and rank them from highest to lowest weight. This css specificity calculator follows the CSS Selectors Level 4 specification, handling :is(), :not(), :where() and pseudo-elements correctly. It runs entirely in your browser so no code is uploaded.

Separate multiple selectors with newlines to compare and rank them.

Result

  • Highest specificity
    (1, 2, 2)

    #header .nav li a:hover

  • Lowest specificity
    (0, 0, 1)

    :where(.container) p

  • Selectors compared
    5
SelectorSpecificity
#header .nav li a:hover(1, 2, 2)
ul li.active > a(0, 1, 3)
:is(h1, h2, .title)(0, 1, 0)
:not(.hidden)(0, 1, 0)
:where(.container) p(0, 0, 1)

How to use the css specificity calculator

  1. Paste one or more CSS selectors into the text area, placing each selector on its own line.
  2. The css specificity calculator parses every selector and computes its (a, b, c) tuple automatically.
  3. Review the ranked table to see which selector has the highest css selector specificity.
  4. Use the results to debug cascade conflicts or verify that your stylesheets apply rules in the expected order.

How CSS Selector Specificity Is Calculated

The CSS Selectors Level 4 specification defines specificity as a three-part tuple written as (a, b, c). Each part counts a different category of simple selectors:

  • a counts ID selectors such as #header.
  • b counts class selectors (.nav), attribute selectors ([type="text"]) and pseudo-classes (:hover, :nth-child(2)).
  • c counts type selectors (div, p) and pseudo-elements (::before, ::first-line).

The universal selector * and combinators like >, + and ~ contribute zero to all three parts. To calculate the specificity of ul#nav li.active a:hover, count one ID (a=1), two classes or pseudo-classes for .active and :hover (b=2), and three type selectors for ul, li and a (c=3). The result is (1, 2, 3).

Specificity Rules for :is(), :not() and :where()

Selectors Level 4 changed how functional pseudo-classes affect the specificity calculation. Understanding these rules is essential when using any specificity calculator.

The :is() and :not() pseudo-classes take the specificity of their most specific argument. For example, :is(h1, .title, #main) evaluates to (1, 0, 0) because the ID selector #main is the heaviest argument, even if the element only matches h1.

The :where() pseudo-class always contributes (0, 0, 0) regardless of its arguments. It was designed specifically to allow grouping without adding weight.

The :has() pseudo-class follows the same rule as :is(): it takes the specificity of its most complex argument. :nth-child(2n+1 of .item, #main) counts as one pseudo-class plus the most specific selector after of, and :host(.theme) and ::slotted(.item) add the specificity of the selector inside the brackets to their own weight.

Common Specificity Values Reference

This table shows typical selectors and their computed tuples. Use it as a quick reference alongside the calculator.

SelectorSpecificityNotes
*(0, 0, 0)Universal selector adds nothing
p(0, 0, 1)Single type selector
.btn(0, 1, 0)Single class
[href](0, 1, 0)Attribute selector counts as class-level
:hover(0, 1, 0)Pseudo-class
::before(0, 0, 1)Pseudo-element counts as type-level
#logo(1, 0, 0)ID selector
div.wrapper#main p::first-letter(1, 1, 3)Mixed selector
:where(.x, #y)(0, 0, 0):where zeroes out

Why Specificity Matters in Practice

When two rules target the same element, the browser applies the one with higher css selector specificity. If both have identical specificity, the rule that appears later in the stylesheet wins. Misunderstanding this cascade behavior is one of the most common sources of styling bugs.

A frequent mistake is relying on IDs everywhere because they are easy to override. A single ID selector (1, 0, 0) outweighs any number of class selectors, meaning you would need eleven classes just to tie one ID. This makes stylesheets hard to maintain. Modern best practice favors low-specificity selectors built from classes, combined with :where() to intentionally reset weight when needed.

Another edge case involves pseudo-elements. Developers sometimes confuse :before (single colon, legacy syntax) with ::before (double colon, standard syntax). Both are parsed as pseudo-elements and add to the c component, but using the double-colon form avoids ambiguity.

Comparing Multiple Selectors

To compare selectors, enter each one on a separate line. The tool ranks them from highest to lowest specificity. Comparison uses the tuple lexicographically: first compare a, then b, then c. A selector with (1, 0, 0) always beats one with (0, 99, 99).

This ranking helps when auditing large stylesheets or migrating from older frameworks. Pair this analysis with tools like a css formatter to keep your code readable after refactoring selectors for lower specificity.

A line with several selectors separated by commas is split, and each selector gets its own row. A selector that cannot be read, such as one with an unclosed bracket, is listed as invalid at the end of the table. The nesting selector & is counted as zero, because its weight depends on the parent rule.

Worked examples

ExampleInputResult
ID vs class vs elementCSS selectors (one per line): #main / .intro / divHighest specificity: (1, 0, 0); Lowest specificity: (0, 0, 1); Selectors compared: 3
Selectors Level 4 functionsCSS selectors (one per line): :is(#a, .b) / :not(.c) / :where(.d)Highest specificity: (1, 0, 0); Lowest specificity: (0, 0, 0); Selectors compared: 3
Complex real-world selectorsCSS selectors (one per line): body #content .post p::first-line / ul.nav > li a:hover / [data-theme="dark"] .btnHighest specificity: (1, 1, 3); Lowest specificity: (0, 2, 0); Selectors compared: 3

FAQ

What does the (a, b, c) tuple mean in CSS specificity?

The tuple represents three counters: a for ID selectors, b for class selectors, attribute selectors and pseudo-classes, and c for type selectors and pseudo-elements. Higher values in earlier positions always outweigh later ones.

Does the universal selector (*) add specificity?

No. The universal selector and combinators such as >, + and ~ contribute (0, 0, 0) and do not affect the specificity calculation.

How does :is() affect css selector specificity?

The :is() pseudo-class takes the specificity of its most specific argument. For example, :is(p, .cls, #id) has a specificity of (1, 0, 0) because the ID selector is the heaviest.

What is the specificity of :where()?

The :where() pseudo-class always has a specificity of (0, 0, 0), no matter what selectors are passed inside it. It is useful for grouping without increasing weight.

Do inline styles count in this specificity calculator?

Inline styles applied via the style attribute are not selectors. They sit above all selector-based rules in the cascade. This tool calculates selector specificity only.

Is there a maximum specificity value in CSS?

The specification does not define a hard limit, but browsers typically store each component as an integer. In practice, selectors rarely exceed a few dozen in any single component.

Can I use this tool offline?

Yes. The css specificity calculator runs entirely in your browser. No data is sent to a server, so it works offline once the page is loaded.