Developer Tools
CSS Specificity Calculator - Understand Selector Weight
Calculate and compare CSS selector specificity scores (a,b,c,d). Instantly see which rule wins and why, with support for :is(), :not(), :where(), and pseudo-elements.
Examples
0,1,2,1
How CSS specificity works
The CSS cascade uses specificity to decide which rule wins when two or more selectors target the same element. Specificity is expressed as four numbers (a,b,c,d):
- a: Inline styles (
style="…"). Always 1 for inline, 0 for stylesheets. - b: ID selectors (
#id) - c: Class selectors (
.class), attribute selectors ([attr]), and pseudo-classes (:hover,:nth-child) - d: Type selectors (
div,p) and pseudo-elements (::before,::after)
Comparison is left-to-right: a higher a always beats any b, and so on. The
universal selector (*) and combinators (>, +, ~) contribute 0 to specificity.
Modern pseudo-class specificity
:where(): Always 0. Useful for base styles you want easily overridden.-
:is()and:not(): Take the specificity of their most specific argument. :has(): Same as:is().
Tips for managing specificity
- Prefer classes over IDs in CSS to keep specificity manageable.
- Avoid nesting selectors too deeply, as each level adds to specificity.
-
Use
:where()for reusable utilities that should never win a specificity battle. - Reserve
!importantfor truly exceptional cases like utility overrides.
!important
The !important declaration overrides all specificity calculations, making a rule "win"
no matter what. Example:
.button {
color: blue !important; /* Always wins */
} Why it's bad practice: It creates an "arms race" - once one rule uses
!important, the only way to override it is with another !important,
making the cascade unpredictable.
When it's legitimate: Utility classes that must override component styles
(e.g., Tailwind's .hidden), third-party style resets where you can't control load
order, or critical accessibility fixes.
Cascade layers (@layer)
CSS Cascade Layers (introduced in 2022, supported in all modern browsers) let you explicitly declare the priority order of entire groups of rules:
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; }
}
@layer utilities {
.hidden { display: none !important; }
}
Layers are evaluated before specificity: a rule in the utilities layer always
beats a rule in the components layer, regardless of selector specificity. This eliminates
specificity battles entirely when you structure your CSS into layers.
Specificity visualization
Compare these three selectors:
| Selector | Specificity (a,b,c,d) | Explanation |
|---|---|---|
p | (0,0,0,1) | 1 type selector |
.button | (0,0,1,0) | 1 class |
#header .nav a:hover | (0,1,2,1) | 1 ID + 1 class + 1 pseudo-class + 1 type |
Winner: #header .nav a:hover because it has an ID (b=1). Even if .button had 100 classes, it would still lose because b=0.