How inline styles and !important fit into the cascade
Best practices for writing maintainable, predictable CSS
Introduction to the Cascade
The "Cascade" in CSS is the algorithm that determines which styles ultimately apply to an element
when multiple rules compete. It's one of the most important—and often misunderstood—features of CSS.
Understanding the cascade helps you write CSS that behaves predictably. You'll know exactly why
one rule overrides another, and you'll be able to structure your stylesheets to avoid specificity
battles and the dreaded !important hack.
What is the Cascade?
When multiple CSS rules could apply to the same element, the cascade determines the winner
using a specific order of priority:
Origin and Importance - Where the CSS comes from:
Browser default styles (user agent)
User preferences
Author styles (your CSS)
!important declarations (reverse order)
Specificity - How specific the selector is (if same origin)
Source Order - Position in the stylesheet (if same specificity)
Understanding Specificity
Specificity is calculated as three numbers: (a, b, c). Each part counts
different types of selectors. Think of it like a three-digit number where the leftmost
digit has the most weight.
The Specificity Formula
a = Count of ID selectors
b = Count of class selectors, attribute selectors, and pseudo-classes
c = Count of element selectors and pseudo-elements
Quick Reference Table
/* Specificity Examples */
p /* (0, 0, 1) - 1 element */
.button /* (0, 1, 0) - 1 class */
#header /* (1, 0, 0) - 1 ID */
div p /* (0, 0, 2) - 2 elements */
.nav .item /* (0, 2, 0) - 2 classes */
ul li:first-child /* (0, 1, 2) - 1 pseudo-class, 2 elements */
#main .content p /* (1, 1, 1) - 1 ID, 1 class, 1 element */
button[type="submit"]/* (0, 1, 1) - 1 attribute, 1 element */
.btn.primary.large /* (0, 3, 0) - 3 classes */
Interactive Specificity Calculator
This demo shows how specificity is calculated for various selectors and how they
compare to each other:
Specificity in Action
Let's see a practical demonstration of how different specificity levels compete
for control of an element's styling. Watch how higher specificity always wins:
/* Element selector - (0, 0, 1) */
p {
color: gray;
}
/* Class selector - (0, 1, 0) - WINS over element */
.styled {
color: blue;
}
/* ID selector - (1, 0, 0) - WINS over class */
#special {
color: green;
}
/* Two classes - (0, 2, 0) - WINS over one class */
.styled.important {
color: red;
}
/* Descendant combinator - (0, 1, 1) */
div.container p {
color: purple;
}
Notice how the element with class="styled" and id="special"
is styled by the ID rule because (1, 0, 0) beats (0, 1, 0).
This is why using IDs for styling can make your CSS hard to override.
Source Order
When two selectors have exactly the same specificity, the one that appears
last in the CSS wins. This is called "source order."
/* Both have specificity (0, 1, 0) */
.box {
color: blue;
background: lightblue;
}
.box {
color: red; /* This wins */
background: pink; /* This wins */
}
Inline Styles
Inline styles (using the style attribute) have higher specificity than
any CSS selector. They're effectively calculated as (1, 0, 0, 0)—an
extra digit that beats everything.
<!-- Inline styles beat all CSS selectors -->
<div id="styled-box" style="color: red;">
This will be red, even if #styled-box { color: blue }
</div>
The !important Declaration
Adding !important to a declaration gives it the highest priority,
overriding even inline styles (unless the inline style also uses !important).
/* Low specificity, but !important makes it win */
.override {
color: orange !important;
}
/* High specificity, but loses to !important */
#high-specificity {
color: blue;
}
Comparing Specificity Values
To compare specificity, read from left to right. The first number that differs
determines the winner:
Examples
(1, 0, 0) beats (0, 10, 0) One ID beats ten classes
(0, 2, 1) beats (0, 1, 10) Two classes beat one class (the element count doesn't matter)
(0, 1, 1) beats (0, 1, 0) When first two numbers tie, check the third
Best Practices
Understanding specificity helps you write maintainable CSS. Here are key strategies
to keep your stylesheets predictable and manageable:
Keep Specificity Low
Favor classes over IDs for styling
Avoid long descendant chains like .nav ul li a span
Use single class names when possible: .button instead of div.container .button
Reserve high specificity for truly exceptional cases
Keep Specificity Consistent
If most rules use (0, 1, 0), don't suddenly use (1, 0, 0)
Inconsistent specificity makes overriding styles unpredictable
Consider using a naming methodology like BEM to maintain consistency
Document any intentionally high-specificity rules
Use IDs for Functionality
Reserve IDs for JavaScript hooks and fragment identifiers
Style with classes, which are reusable and have lower specificity
This separation makes both your CSS and JavaScript easier to maintain
Avoid !important
Only use it for utility classes that must always apply
If you need it often, refactor your CSS structure
It makes debugging extremely difficult
Once you start using it, it tends to spread throughout your codebase