CSS Specificity Calculator

Calculate (a, b, c) specificity scores, compare selectors, and learn which rule wins.

CSS Selectors (one per line)
IDs (b) Classes / Attrs / Pseudo-classes (c) Elements / Pseudo-elements (d)
Enter CSS selectors above to calculate specificity.

How to Use the CSS Specificity Calculator

  1. Batch mode — paste one or more CSS selectors (one per line) to calculate and rank all of them at once.
  2. Compare mode — enter two selectors side by side to see which one wins and why.
  3. Quiz mode — test your knowledge by guessing which of two selectors has higher specificity.
  4. Read the bars — red bars show ID count, green bars show class/attribute/pseudo-class count, blue bars show element/pseudo-element count.

How CSS Specificity Works

Specificity is the algorithm CSS uses to determine which rule applies when multiple declarations target the same element and property. It is calculated as a three-number score (a, b, c) — sometimes written (0, 0, 0) or as three digits separated by commas. A higher leftmost number always wins, regardless of how large the rightmost numbers are.

The three columns represent: (a) inline styles — applied via the style attribute, always the most specific; (b) ID selectors — selectors using #id; (c) class, attribute, and pseudo-class selectors.class, [attr], :hover; and within column c there is an additional sub-count for element selectors and pseudo-elements (div, ::before).

Specificity Scoring Table

  • Inline style (style="…") — (1, 0, 0, 0)
  • ID selector (#id) — (0, 1, 0, 0)
  • Class selector (.class) — (0, 0, 1, 0)
  • Attribute selector ([href], [type="text"]) — (0, 0, 1, 0)
  • Pseudo-class (:hover, :first-child, :not(x)) — (0, 0, 1, 0)
  • Element selector (div, p, a) — (0, 0, 0, 1)
  • Pseudo-element (::before, ::after, ::first-line) — (0, 0, 0, 1)
  • Universal selector (*) — (0, 0, 0, 0)
  • Combinators (+, >, ~, space) — (0, 0, 0, 0)

Special Cases

Several modern CSS selectors have non-obvious specificity behaviors. :not() has no specificity of its own, but its argument contributes. :is() takes the highest specificity of all selectors inside it — so :is(#id, .class) has the specificity of #id. :where() always contributes zero specificity, making it useful for low-specificity utility selectors that are easy to override. CSS layers (@layer) interact with specificity in a layered cascade that is separate from selector specificity.

Common Specificity Mistakes

  • Using #id in component CSS makes it nearly impossible to override without another ID or !important
  • Deeply nesting selectors (.page .content .section .title) creates unnecessarily high specificity
  • Overusing !important to "fix" specificity issues creates a maintenance nightmare
  • Assuming more element selectors will beat a class — they never will (1000 elements = score of 1000 in column c, but one class also scores 1 in column b which is higher)

Best Practices for Managing Specificity

Modern CSS methodologies like BEM (Block Element Modifier), ITCSS, and utility-first frameworks like Tailwind are largely designed to control specificity. BEM keeps all component styles at a single-class specificity (0, 0, 1, 0), making them easy to override. ITCSS layers styles from least specific (elements) to most specific (utilities, overrides). CSS custom properties (variables) are resolved before the cascade, so they are useful for theming without specificity conflicts. For deeper learning, also explore the CSS Unit Converter and Easing Editor.

Frequently Asked Questions

CSS specificity is calculated as three numbers (a, b, c): a counts inline styles, b counts ID selectors (#id), and c counts class selectors (.class), attribute selectors ([attr]), pseudo-classes (:hover), element selectors (div, p), and pseudo-elements (::before). The universal selector (*) and combinators contribute 0.
Yes. !important overrides all specificity calculations. When two competing declarations both use !important, specificity and source order rules apply between them. Best practice is to avoid !important in component CSS and instead increase specificity through better selector structure.
:not() itself has no specificity, but its argument contributes its specificity to the overall score. :is() takes the highest specificity of any selector in its list. :where() always has zero specificity regardless of its contents — it is the low-specificity alternative to :is().
A class selector (.example) always has higher specificity than an element selector (div). A single class produces a score of (0,1,0) while a single element produces (0,0,1). You would need 10 element selectors to equal one class in the same column — but in practice one class always beats any number of elements because they are in different columns.
Yes. When two rules have exactly equal specificity, the one that appears later in the stylesheet wins. This is the cascade. Source order is the tiebreaker after specificity, origin (browser default vs. author vs. user), and !important are all considered.