Cascade and specificity
Often several rules act on the same element at once, and they argue with each other: one makes the text gray, another makes it red. The browser settles such arguments by clear rules. This mechanism gave CSS its name: the cascade is the order in which styles "flow down" onto elements.
Order of rules
If two rules with identical selectors set the same property, the one written lower wins:
<style>
p { color: royalblue; }
p { color: crimson; }
</style>
<p>The text is red: the second rule is lower.</p>Properties the rules do not argue about add up: if the first sets the color and the second sets the size, the element gets both.
Specificity
When the selectors differ, their specificity — how precise they are — matters more than the order. An id selector is more precise than a class, and a class is more precise than a tag:
<style>
.warning { color: crimson; }
p { color: gray; }
</style>
<p class="warning">The class beats the tag — red text, even though the p rule is lower.</p>| Selector | Weight |
|---|---|
p, h1, li | tag — the weakest |
.note, [type="text"], :hover | class, attribute, pseudo-class |
#logo | id — stronger than any number of classes |
style="..." | the style attribute — stronger than any selector |
Comparing selectors
Specificity is counted as three numbers: how many ids the selector has, how many classes and how many tags. They are compared left to right, like version numbers. .card p is 0 ids, 1 class, 1 tag, while p is 0, 0, 1, so the first one is stronger:
<style>
.card p { color: seagreen; }
p { color: gray; }
</style>
<div class="card">
<p>Inside the card — green.</p>
</div>
<p>Outside the card — gray.</p>Inheritance
Some properties are inherited: set them on a parent and they pass to every element inside. Text properties behave this way — color, font-family, font-size, line-height:
<style>
.article {
color: darkslateblue;
border: 2px solid gold;
}
</style>
<div class="article">
<p>The paragraph inherited the color but not the border.</p>
</div>Borders, spacing and backgrounds are not inherited — otherwise every nested element would get its own border.
An inherited value loses to any rule
A value received from the parent loses even to the weakest rule written for the element itself:
<style>
#box { color: crimson; }
a { color: seagreen; }
</style>
<div id="box">
The text is red, and the <a href="#">link</a> is green.
</div>The #box selector is strong, but it targets the div. The link has its own a rule, and that rule beats the inherited color.
Common mistake
The word !important after a value overrides any selector. It looks like a quick fix, but the next change will need another !important, and the styles turn into a race. It is better to find which selector gets in the way and make yours more precise:
<style>
.card p { color: gray; }
.card .price { color: seagreen; }
</style>
<div class="card">
<p>Product description</p>
<p class="price">$25</p>
</div>.card .price (two classes) is stronger than .card p (a class and a tag), so the price is green without any !important.