Master the art of CSS specificity with comprehensive examples, interactive tools, and real-world scenarios
CSS specificity is the algorithm used by browsers to determine which CSS rule should be applied when multiple rules target the same element. It's like a scoring system that helps resolve conflicts between competing styles.
When multiple CSS rules apply to the same element, the browser uses specificity to determine which rule wins. The rule with the highest specificity value takes precedence.
Specificity is calculated using four values, often written as (a,b,c,d):
Enter a CSS selector to calculate its specificity value:
| Selector Type | Example | Specificity (a,b,c,d) | Decimal Value | Description |
|---|---|---|---|---|
| Universal | * |
(0,0,0,0) | 0 | Selects all elements |
| Element | div, p, h1 |
(0,0,0,1) | 1 | Selects HTML elements by tag name |
| Pseudo-element | ::before, ::after |
(0,0,0,1) | 1 | Selects virtual elements |
| Class | .button, .nav |
(0,0,1,0) | 10 | Selects elements by class attribute |
| Attribute | [type="text"], [href] |
(0,0,1,0) | 10 | Selects elements by attribute |
| Pseudo-class | :hover, :focus, :nth-child() |
(0,0,1,0) | 10 | Selects elements in specific states |
| ID | #header, #main |
(0,1,0,0) | 100 | Selects elements by ID attribute |
| Inline Style | style="color: red;" |
(1,0,0,0) | 1000 | Styles applied directly to element |
| !important | color: red !important; |
∞ | ∞ | Overrides all other declarations |
/* CSS Rules */
p { color: blue; } /* (0,0,0,1) = 1 */
.text { color: green; } /* (0,0,1,0) = 10 */
#main { color: orange; } /* (0,1,0,0) = 100 */
<p style="color: red;"> /* (1,0,0,0) = 1000 */
/* HTML */
<p id="main" class="text" style="color: red;">
What color will this text be?
</p>
/* Result: RED (inline style wins) */
/* CSS Rules */
div p { color: black; } /* (0,0,0,2) = 2 */
.content p { color: blue; } /* (0,0,1,1) = 11 */
#main .content p { color: green; } /* (0,1,1,1) = 111 */
#main .content p:first-child { color: red; } /* (0,1,2,1) = 121 */
#main .content p.highlight { color: purple; } /* (0,1,2,1) = 121 */
/* HTML */
<div id="main">
<div class="content">
<p class="highlight">This text will be PURPLE</p>
<p>This text will be RED (first-child)</p>
</div>
</div>
/* CSS Rules */
#main .content p {
color: blue !important; /* !important wins */
}
.text {
color: red;
}
/* HTML */
<div id="main">
<div class="content">
<p class="text" style="color: green;">
This will be BLUE (!important overrides inline)
</p>
</div>
</div>
/* 1. Base styles (low specificity) */
p { font-size: 16px; line-height: 1.5; }
/* 2. Layout components */
.container { max-width: 1200px; margin: 0 auto; }
/* 3. UI components */
.button { padding: 10px 20px; border-radius: 4px; }
.button--primary { background: blue; color: white; }
/* 4. State modifiers */
.button:hover { opacity: 0.8; }
.button.is-disabled { opacity: 0.5; pointer-events: none; }
/* 5. Utility classes (higher specificity when needed) */
.text-center { text-align: center !important; }
.hidden { display: none !important; }
Issue: Your CSS rule isn't being applied to an element.
Solution:
Issue: Bootstrap/Foundation styles are overriding your custom CSS.
Solution:
/* Instead of this (low specificity) */
.button { background: red; }
/* Use this (higher specificity) */
.my-app .button { background: red; }
/* Or use CSS custom properties */
:root { --button-bg: red; }
.button { background: var(--button-bg); }
Issue: Too many !important declarations making CSS unmaintainable.
Solution:
CSS Cascade Layers provide a new way to manage specificity:
@layer base, components, utilities;
@layer base {
p { color: black; }
}
@layer components {
.text { color: blue; } /* This wins over base layer */
}
@layer utilities {
.text-red { color: red; } /* This wins over components */
}
Custom properties follow normal inheritance rules but can help reduce specificity conflicts:
:root {
--primary-color: blue;
--text-color: black;
}
.component {
color: var(--text-color);
background: var(--primary-color);
}
/* Easy to override without specificity wars */
.dark-theme {
--primary-color: darkblue;
--text-color: white;
}
Container queries don't add to specificity, but the selectors inside them do:
@container (min-width: 400px) {
.card { padding: 2rem; } /* (0,0,1,0) */
.card .title { font-size: 2rem; } /* (0,0,1,1) */
}