CSS Specificity Calculator computes the specificity score of any CSS selector. Paste one or more selectors (e.g., .nav ul li a:hover, #header .logo, *) to see their specificity as a three-number tuple (A, B, C) and understand which selector would win in a conflict. Also explains why your CSS rule is being overridden and suggests how to fix specificity issues without resorting to !important.
CSS specificity determines which rule wins when two rules target the same element with conflicting declarations. Specificity is calculated as a three-tuple (A, B, C): A = number of ID selectors (#id), B = number of class selectors (.class), attribute selectors ([attr]), and pseudo-classes (:hover, :nth-child), C = number of type selectors (div, p) and pseudo-elements (::before, ::after). Higher A wins; if A is equal, higher B wins; if B is equal, higher C wins. The universal selector (*), combinators, and :where() all have specificity 0.
Specificity best practices: use class selectors (.component) for styling rather than IDs (#header) -- IDs are almost impossible to override without !important. The BEM methodology (Block__Element--Modifier) keeps all selectors at one-class specificity. CSS Layers (@layer) let you define a specificity-independent ordering -- rules in later layers win regardless of specificity within that layer. :is() and :not() take the specificity of their most specific argument.
ID vs class
Result: #nav (1,0,0) beats .nav (0,1,0) -- ID selectors always win over class selectors
Complex class chain
Result: .nav .menu .item:hover = (0,3,0) -- three classes, one pseudo-class = B value of 3
Type + class
Result: div.container p.text = (0,2,2) -- two classes (B=2) + two types (C=2)
How is CSS specificity calculated?
Specificity is calculated as (A, B, C): A = count of ID selectors (#id). B = count of class selectors (.class), attribute selectors ([href]), and pseudo-classes (:hover, :focus, :nth-child(), :not(), :is()). C = count of type selectors (div, p, span) and pseudo-elements (::before, ::after, ::placeholder). Not counted: universal selector (*), combinators (space, >, +, ~), :where() (always 0 specificity), :is()/:not() contribute the specificity of their most specific argument. Inline styles (style attribute) beat any selector (effectively A=1 in an unstated fourth slot). !important overrides everything.
What is the difference between :is() and :where() in terms of specificity?
:is() takes the specificity of its most specific argument: :is(#id, .class) has specificity (1,0,0) -- the ID wins. This means using :is() with an ID makes the whole rule high-specificity. :where() always has 0 specificity regardless of its arguments: :where(#id, .class) has specificity (0,0,0). Use :where() when you want to apply styles without affecting the specificity cascade -- great for base styles and resets. Use :is() when you want the selector grouping shorthand with normal specificity behavior. Both accept the same selector list syntax.
How do CSS Layers affect specificity?
@layer (CSS Cascade Layers, 2022) changes the cascade priority without specificity. Define layers in order: @layer base, components, utilities; -- utilities beats components beats base, regardless of specificity. A low-specificity rule in utilities beats a high-specificity rule in base. This solves the specificity arms race in large codebases. Unlayered styles always beat layered styles (important for third-party libraries -- wrap them in a layer to prevent override issues). Tailwind CSS v4 uses cascade layers internally for its utility classes.
How do I fix a specificity conflict without using !important?
Strategies to increase specificity: Add a more specific selector (add a parent class or ID context). Repeat a class selector: .button.button (doubles the class specificity, poor practice). Attribute selector trick: [class~='button'] is equivalent specificity to .button. Better approaches: restructure your CSS to avoid the conflict (often a sign of poor architecture). Use CSS Layers to define priority at the architecture level. Refactor to use BEM (all selectors are single-class). For third-party CSS conflicts: wrap the library in @layer base {} so your styles always win.
What does !important do and when should I use it?
!important overrides any specificity -- an !important declaration beats all non-important declarations regardless of specificity. Multiple !important declarations are resolved by specificity (higher specificity !important wins). When to use !important: utility classes that should always apply (Tailwind-style overrides), accessibility styles that must not be overridden (forced color mode), critical user preferences. When NOT to use: to fix specificity conflicts in your own code (fix the architecture instead), to override third-party styles without cascade layers (use @layer base { } instead), anywhere you will regret it in 6 months.