The Cascade, Specificity, and Inheritance
You now know there are three ways to write CSS: Inline, Internal, and External. But what happens when you accidentally apply two different styles to the same element?
The browser doesn't guess; it uses a strict set of rules known as the Cascade to determine which style wins. The Cascade is the process that combines three core concepts to resolve conflicts and apply the final styles:
- The Cascade: Where does the style come from?
- Specificity: How detailed is the selector?
- Inheritance: Does the element automatically get its parent's style?
1. The Cascade: Order and Sourceβ
The Cascade is the primary system for layering styles. It decides the initial winner based on the origin and order of the stylesheet.
Source Order (The "Where" of the Style)β
Styles are prioritized based on their source. Think of it as a river flowing downhillβstyles closer to the element tend to flow last and have more power:
| Priority | Source | Description |
|---|---|---|
| Highest | User Styles (High Specificity) | Styles applied directly by the user (e.g., accessibility settings). |
| 2nd Highest | Author's Styles (!important) | Any rule in your CSS file marked with !important. |
| 3rd Highest | Author's Styles (Normal) | Your External, Internal, and Inline styles (where Specificity rules the day). |
| Lowest | Browser Default Styles | Default styles set by the browser (e.g., blue links, large <h1>). |
The Role of Order:β
If two rules have the exact same Specificity (we'll cover this next) and come from the same source (e.g., two rules in your external stylesheet), the last rule defined wins.
p { color: blue; } /* This rule is defined first. */
p { color: red; } /* This rule is defined last, so all <p> text will be RED. */
2. Specificity: Who is More Precise?β
When two or more selectors try to style the same element, the browser calculates which selector is more specific. The selector with the highest specificity score always wins, regardless of where it appears in the CSS file (unless it's overridden by !important).
Specificity is calculated by counting different types of selectors. Think of it as a four-digit number , where the highest number in the most significant column wins.
Specificity Score Breakdownβ
| Letter | Selector Type | Example | Value |
|---|---|---|---|
| A | Inline Styles | <div style="..."> | 1000 |
| B | IDs | #main-nav | 100 |
| C | Classes, Attributes, Pseudo-classes | .card, [type="text"], :hover | 10 |
| D | Elements and Pseudo-elements | p, div, ::after | 1 |
Specificity Exampleβ
Let's compare two conflicting selectors:
| Selector | Score (A, B, C, D) | Total | Result |
|---|---|---|---|
h1 | (0, 0, 0, 1) | 1 | Loses |
.header-title | (0, 0, 1, 0) | 10 | Wins (The class is 10 times more specific than the element.) |
| Selector | Score (A, B, C, D) | Total | Result |
|---|---|---|---|
#sidebar p | (0, 1, 0, 1) | 101 | Wins |
.card .title | (0, 0, 2, 0) | 20 | Loses (ID selector is 100 points, dominating the score.) |
Never use Inline Styles and try to reserve ID selectors (#) for JavaScript targeting rather than styling, as their high specificity makes CSS harder to override and maintain.
The Power of !importantβ
The !important keyword is the nuclear option of CSS. When added to a declaration, it instantly makes that style rule override all other rules, regardless of specificity.
/* This style will win over any ID, Class, or Element selector */
p {
color: green !important;
}
/* Even if an ID tries to override it, the !important rule wins */
#main-content p {
color: red; /* This will be ignored */
}
!importantAvoid using !important! It breaks the natural cascade flow and specificity rules, making your code extremely difficult to debug and maintain. Only use it in rare cases like:
- Overriding third-party library styles where you can't edit the source CSS.
- Utility classes (e.g.,
.u-hidden { display: none !important; }).
3. Inheritance: Borrowing Styles from Parentsβ
The final piece of the puzzle is Inheritance. Certain CSS properties are passed down (inherited) from a parent element to its child elements.
Inherited Propertiesβ
Properties related to text and typography typically inherit:
colorfont-familyfont-sizeline-heighttext-align
Non-Inherited Propertiesβ
Properties related to the Box Model and Layout do not inherit:
marginpaddingborderwidth/heightbackground-color
Inheritance Exampleβ
<div style="font-family: Georgia, serif; border: 1px solid black;">
<p>This paragraph inherits the font from its parent <div>.</p>
<p style="border: none;">But it DOES NOT inherit the border or padding.</p>
</div>
The browser applies the font-family to the <p> elements, but since border is not inherited, the <p> tags will not have a border unless one is specifically declared for them.
Interactive Cascade Order Demoβ
This interactive example shows how Specificity (ID vs. Class) and Source Order (last rule wins) determine the final style.
In the CSS panel, try changing the color values and observe which rule wins based on the selector's power.
Observationsβ
- The first paragraph's color is Purple because the ID selector (
#intro-paragraph) has the highest Specificity score (100), overriding the Class (.main-text, score 10) and Element (p, score 1) selectors. - The
font-weightis Bold because it is set by the Class selector (Rule 2), and the ID selector (Rule 3) does not attempt to change thefont-weight, allowing the inherited property to apply. - The second paragraph (which has no class or ID) should take the color of the last
prule defined in the CSS if they were the only ones present. However, because the class and ID rules are present, they dominate the first paragraph.
The Cascade is a complex dance of Specificity first, and Source Order second.