When multiple CSS rules target the same element with conflicting styles, how does the browser decide which one wins? The answer lies in understanding specificity, the cascade, and inheritance. These are fundamental concepts that explain how CSS actually works and are essential for writing predictable, maintainable stylesheets.
The Problem: Conflicting Styles
Consider this scenario where multiple CSS rules style the same element:
/* Which color wins? */
p {
color: blue;
}
.intro {
color: red;
}
#special {
color: green;
}
p.intro {
color: purple;
}<p class="intro" id="special">What color am I?</p>All four rules target the same paragraph. Without understanding specificity and the cascade, it's impossible to predict the final color. Let's learn the rules that govern CSS!
Conflicting Styles - Which Wins?
What Is Specificity?
Specificity is a weight that determines which CSS rule is applied when multiple rules could apply to the same element. It's calculated based on the types of selectors used in a rule.
Think of specificity as a scoring system. Each type of selector has a different point value, and the rule with the highest score wins.
Key Concept: Specificity is like a competition where each selector type has different voting power. ID selectors have the most power, class selectors have medium power, and element selectors have the least power.
The Specificity Hierarchy
CSS specificity is calculated using a four-part value, often represented as (a, b, c, d):
1000 points
100 points
10 points
1 point
Specificity Values
| Property | Values | Description |
|---|---|---|
Inline styles | 1-0-0-0 | Highest specificity (1000 points) |
IDs | 0-1-0-0 | 100 points per ID |
Classes, attributes, pseudo-classes | 0-0-1-0 | 10 points per class/attribute/pseudo-class |
Elements, pseudo-elements | 0-0-0-1 | 1 point per element/pseudo-element |
Universal (*), combinators (+, >, ~) | 0-0-0-0 | 0 points (no specificity) |
Calculating Specificity
Let's calculate specificity for different selectors step by step:
Simple Examples
/* 0-0-0-1 = 1 point */
p { }
/* 0-0-1-0 = 10 points */
.intro { }
/* 0-1-0-0 = 100 points */
#header { }
/* 0-0-0-2 = 2 points */
p span { }
/* 0-0-1-1 = 11 points */
p.intro { }
/* 0-1-0-1 = 101 points */
#header p { }Complex Examples
/* 0-0-2-1 = 21 points */
/* .nav (10) + :hover (10) + a (1) */
.nav a:hover { }
/* 0-1-1-2 = 112 points */
/* #main (100) + .content (10) + p (1) + span (1) */
#main .content p span { }
/* 0-0-3-0 = 30 points */
/* .btn (10) + .btn-primary (10) + :hover (10) */
.btn.btn-primary:hover { }
/* 0-2-1-1 = 211 points */
/* #header (100) + #nav (100) + .link (10) + a (1) */
#header #nav .link a { }
/* 0-0-0-0 = 0 points */
/* Universal selector has no specificity */
* { }
/* 0-0-1-2 = 12 points */
/* Combinators don't add specificity */
/* .parent (10) + > (0) + p (1) + span (1) */
.parent > p span { }Specificity in Action
🧮 Specificity Calculator:
When counting specificity, think in columns, not as a single number. (0, 1, 0, 0) always beats (0, 0, 10, 0) even though 10 is larger than 1. Each column is more powerful than all columns to its right combined!
Important Specificity Rules
Rule 1: Inline Styles Always Win
Inline styles (added directly to HTML elements) have the highest specificity and will override any CSS in stylesheets:
Inline Styles Override Everything
Best Practice: Avoid inline styles in production code. They're hard to maintain, impossible to override without !important, and mix presentation with content. Use classes instead!
Rule 2: !important Trumps Everything
The !important declaration overrides all normal specificity rules (but use it sparingly!):
/* 0-1-0-0 = 100 points */
#special {
color: red !important; /* This wins even against inline styles! */
}
/* 1-0-0-0 = 1000 points (inline style) */
/* <p id="special" style="color: blue;">Text</p> */
/* But the !important declaration above still wins */
/* Multiple !important declarations? Specificity rules apply again */
p {
color: green !important; /* 0-0-0-1 */
}
#special {
color: red !important; /* 0-1-0-0 - This wins! */
}!important Override Power
Warning: Use !important as a last resort. It breaks the natural cascade, makes debugging harder, and creates maintenance nightmares. The only time it's acceptable is for utility classes or when overriding third-party CSS you can't modify.
Rule 3: Equal Specificity? Last One Wins
When two rules have identical specificity, the one that appears last in the CSS file wins:
/* Both have 0-0-1-0 = 10 points */
.text {
color: blue;
}
.text {
color: red; /* This wins - it's last */
}
/* Both have 0-0-0-1 = 1 point */
p {
font-size: 16px;
}
p {
font-size: 20px; /* This wins */
}Source Order Matters (CSS, not HTML)
The Cascade
The "Cascading" in Cascading Style Sheets refers to the algorithm browsers use to determine which styles apply when multiple rules could apply. The cascade considers three main factors in order:
- Importance: !important declarations
- Specificity: How specific the selector is
- Source Order: Which rule comes last
The Complete Cascade Order
When determining which style wins, browsers follow this priority order (highest to lowest):
- 1. User !important declarations
User's custom CSS with !important (accessibility) - 2. Author !important declarations
Your CSS with !important - 3. Author normal declarations
Your regular CSS (uses specificity) - 4. User normal declarations
User's custom CSS without !important - 5. Browser defaults
Browser's default styles (user agent stylesheet)
Note: Most developers only deal with "Author normal declarations" (your CSS) where specificity and source order matter. User stylesheets are rare, and !important should be avoided when possible.
CSS Inheritance
Inheritance is when child elements automatically receive certain CSS property values from their parent elements. Not all properties inherit—only those that make sense to pass down.
Properties That Inherit
Typography and text-related properties typically inherit:
- Font properties: font-family, font-size, font-weight, font-style
- Text properties: color, line-height, letter-spacing, text-align
- List properties: list-style, list-style-type
- Cursor: cursor property
Properties That Don't Inherit
Layout and box model properties don't inherit:
- Box model: margin, padding, border, width, height
- Positioning: position, top, left, etc.
- Display: display, float, clear
- Background: background-color, background-image
CSS Inheritance Example
Controlling Inheritance
You can control inheritance with special keywords:
/* inherit - Force inheritance */
.child {
border: inherit; /* Inherit parent's border */
}
/* initial - Reset to default value */
.element {
color: initial; /* Reset to browser default */
}
/* unset - Inherit if inheritable, otherwise initial */
.element {
color: unset; /* Will inherit from parent */
margin: unset; /* Will reset to initial (0) */
}
/* revert - Revert to browser stylesheet */
.element {
display: revert; /* Back to browser default */
}Inheritance Control Keywords
| Property | Values | Description |
|---|---|---|
inherit | Keyword | Forces property to inherit from parent |
initial | Keyword | Resets property to its initial/default value |
unset | Keyword | Inherits if inheritable, otherwise resets to initial |
revert | Keyword | Reverts to browser's default stylesheet |
Common Specificity Problems and Solutions
Problem 1: Overly Specific Selectors
Using very specific selectors makes styles hard to override:
/* BAD: Too specific (0-1-1-3 = 113 points) */
#header nav ul li a {
color: blue;
}
/* Now you need even MORE specificity to override */
#header nav ul li a.active {
color: red; /* 0-1-2-3 = 123 points needed! */
}
/* BETTER: Use classes (0-0-1-0 = 10 points) */
.nav-link {
color: blue;
}
.nav-link-active {
color: red; /* Easy to override */
}Problem 2: !important Overuse
Using !important creates specificity wars:
/* BAD: !important war */
.button {
background: blue !important;
}
.button-primary {
background: red !important; /* Need !important to override */
}
.button-primary:hover {
background: darkred !important; /* Another !important! */
}
/* BETTER: Use proper specificity */
.button {
background: blue;
}
.button-primary {
background: red; /* Naturally overrides .button */
}
.button-primary:hover {
background: darkred; /* Natural cascade */
}Problem 3: Inline Styles
Inline styles are nearly impossible to override:
<!-- BAD: Inline styles -->
<button style="background: blue; color: white; padding: 10px;">
Click Me
</button>
<!-- Now CSS can't style this without !important -->
<!-- BETTER: Use classes -->
<button class="btn btn-primary">
Click Me
</button>🎯 Best Practices:
- Keep selectors as simple as possible
- Prefer classes over IDs for styling
- Avoid inline styles in production
- Use !important only for utilities or third-party overrides
- Organize CSS from least to most specific
Debugging Specificity Issues
Using Browser DevTools
Modern browsers show you exactly which styles are applied and which are overridden:
Tips for debugging:
- Open DevTools (F12) and inspect the element
- Strikethrough text shows overridden styles
- Look at the file and line number to find the rule
- Hover over selectors to see specificity values
- Temporarily disable rules by unchecking them
Common Symptoms and Solutions
Check: Is there a more specific rule overriding it? Check DevTools for strikethrough styles. Look for IDs, inline styles, or !important declarations.
Fix: Instead of !important, increase specificity by adding a class or make the original rule less specific. !important is usually a sign of poor CSS architecture.
Check: Verify your selector actually matches the element. Check for typos in class names. Ensure the class is actually applied in HTML.
Complete Practical Example
Let's put it all together with a real-world navigation styling scenario:
<nav class="main-nav">
<ul>
<li><a href="#" class="nav-link">Home</a></li>
<li><a href="#" class="nav-link active">About</a></li>
<li><a href="#" class="nav-link">Services</a></li>
<li><a href="#" id="special-link" class="nav-link">Contact</a></li>
</ul>
</nav>/* Base styles - Lowest specificity (0-0-0-1) */
a {
color: blue;
text-decoration: none;
}
/* Navigation links - Medium specificity (0-0-1-0) */
.nav-link {
color: #333;
padding: 10px 15px;
display: block;
transition: background-color 0.3s;
}
/* Hover state - (0-0-2-0) */
.nav-link:hover {
background-color: #f0f0f0;
}
/* Active state - (0-0-2-0) - Same specificity, but comes later */
.nav-link.active {
background-color: #3498db;
color: white;
font-weight: bold;
}
/* Special link with ID - Higher specificity (0-1-0-0) */
#special-link {
color: #e74c3c; /* Overrides .nav-link color */
}
/* But active class still works because it's combined */
#special-link.active {
/* (0-1-1-0) - Highest specificity, wins! */
background-color: #27ae60;
color: white;
}
/* Utility class with !important - Nuclear option */
.text-center {
text-align: center !important; /* Always wins */
}Complete Navigation with Specificity
Key Takeaways
- Specificity determines which CSS rule wins when multiple rules conflict
- Specificity is calculated as (inline, IDs, classes/attributes/pseudo-classes, elements)
- Inline styles (1-0-0-0) have the highest natural specificity
- IDs (0-1-0-0) are more specific than classes (0-0-1-0)
- Classes (0-0-1-0) are more specific than elements (0-0-0-1)
- !important overrides all normal specificity rules
- Equal specificity? The last rule in CSS wins
- The cascade considers importance, specificity, then source order
- Inheritance passes certain properties from parents to children
- Typography properties inherit; box model properties don't
- Keep selectors simple to avoid specificity wars
- Use browser DevTools to debug specificity conflicts
- Avoid inline styles and !important in production code
What's Next?
Congratulations! You've completed the "Selectors & Specificity" section and now understand how CSS actually works under the hood. You know how to target elements precisely with basic selectors, combinators, pseudo-classes, and pseudo-elements. More importantly, you understand how browsers determine which styles to apply through specificity and the cascade.
In the next section, "Colors & Typography", we'll explore how to work with colors, backgrounds, fonts, and text styling. You'll learn about different color formats, gradients, web fonts, and how to create beautiful typography that enhances readability and user experience.
🎓 You've Mastered the Foundation!
Understanding selectors and specificity is fundamental to CSS mastery. These concepts apply to everything you'll learn going forward. With this knowledge, you can now confidently write CSS that behaves predictably and maintain stylesheets that are clean and organized. Great work!