As the size of the website increases and the number of CSS files catering to different pages increase, we can have conflicting design coming from various design sources. CSS is called Cascading Style Sheets since the design cascades from multiple sheets (sources). The bad news is that these properties coming from these multiple sources can sometimes be conflicting. It is CSS that takes up the onerous task of resolving these conflicts! Hence, the word "Cascading" in CSS.
For conflict, the browser in turn uses couple of rules to break the tie. These are based on the following three things: (a) figuring out which rule is the most specific (a value called specificity), (b) ordering of the CSS source, and (c) the importance of the CSS source and the declaration. Let us discuss all three of these in the following sections.
The idea behind specificity is that if we have two rules for the same element, then CSS needs to choose the rule that is more specific.
More formally, the browser uses a value called "specificity" to figure out which CSS property would be the most specific and hence should be given more preference. The order in which we do that is the following (in the order of higher to lower preference): (1) Inline style (using the <style> tag in the page), (2) CSS ID, (3) CSS class, and (4) HTML Tags. In other words, if we have two rules, one is specified with a CSS ID and the other is specified with the tag, then the one that is specified with the CSS ID wins.
The following table lists some examples, where the specificity value is calculated. Basically, we place a value of 1 for each occurrence in a given category (like id or class) and then in the end, a tuple of each value is built.
Selector | With style | ID | Class/Pseudo-Class | Tag/Pseudo-Element | Value |
---|---|---|---|---|---|
body | 0 | 0 | 0 | 1 | (0,0,0,1) |
#id_mesozoic | 0 | 1 | 0 | 0 | (0,1,0,0) |
.class_mesozoic | 0 | 0 | 1 | 0 | (0,0,1,0) |
p.class_mesozoic | 0 | 0 | 1 | 1 | (0,0,1,1) |
One way to think of the specificity is to assign a decimal value to it. Thus, (0,0,0,1) becomes (0 * 1000 + 0 * 100 + 0 * 10 + 1 * 1) or 1. Along the same lines, (0,0,1,1) becomes (0 * 1000 + 0 * 100 + 1 * 10 + 1 * 1) or 11. Since 11 is bigger than 1, then we would prefer the "p.class_mesozoic" over "body"
With that, let us see an example. We have a simple HTML file with a <p> element. The interesting thing is that for the <p> element, we assign both a CSS ID and a CSS class. We do that so that we can generate combinations with both class and the ID values. Next, the corresponding CSS file "cascade_specificity.css" has multiple rules for the <p> element, each with a different specificity value. The idea here is that we should be able to pick the one with the highest specificity. Here is the HTML file:
<!doctype html> <html> <head> <title> Learning CSS: Cascade (Calculating Specificity) </title> <link type="text/css" rel="stylesheet" href="cascade_specificity.css"> </head> <body> <p id="id_mesozoic" class="class_mesozoic">The Mighty T-Rex: <br> Tyrannosaurus were carnivorous dinosaurs that lived during the late Cretaceous period. They were bipedal reptiles with a massive skull that was balanced by a long and heavy tail. Among them, the mightiest and the deadliest were the Tyrannosaurus rex (or T. rex for short). These giants could grow up to 40 feet in length, up to 20 feet in height, and weighed around 7 tons. </p> </body> </html>
And, here is the CSS file. In this file, the CSS rule with the maximum specificity is the "p#id_mesozoic" rule. Accordingly, the browser should select this rule and should ignore the other one.
/* Specificity: (0,0,0,1) or 1 */ p { font-family: Helvetica, sans-serif; color: blue; } /* Specificity: (0,0,1,1) or 11 */ p.class_mesozoic { border: thick dashed red; font-family: Helvetica, sans-serif; color: red; } /* Specificity: (0,1,0,1) or 101 */ p#id_mesozoic { border: thick solid green; font-family: Helvetica, sans-serif; color: green; } /* Specificity: (0,0,1,0) or 10 */ .class_mesozoic { border: thick dotted black; font-family: Helvetica, sans-serif; color: black; }
When we load the file, we would see that the paragraph is using the rule specified in the "p#id_mesozoic" rule.
If we have a case, where we have two rules specified for an element and they have the same specificity (yep, that can happen!), then the last rule to pick the winner is the order in the CSS source (CSS file or CSS style specification).
To see this behavior in action, let us see a simple example. We reuse the earlier HTML file, that has a <p> element. The CSS file "cascade_order.css" has two rules for the <p> element and both of them have the same specificity. We should see that the one specified later gets selected. Here is the HTML file:
<!doctype html> <html> <head> <title> Learning CSS: Cascade (Source Ordering) </title> <link type="text/css" rel="stylesheet" href="cascade_order.css"> </head> <body> <p>The Mighty T-Rex: <br> Tyrannosaurus were carnivorous dinosaurs that lived during the late Cretaceous period. They were bipedal reptiles with a massive skull that was balanced by a long and heavy tail. Among them, the mightiest and the deadliest were the Tyrannosaurus rex (or T. rex for short). These giants could grow up to 40 feet in length, up to 20 feet in height, and weighed around 7 tons. </p> </body> </html>
Let us now see the "cascade_order.css" file. Since both of them are identified using the tag, the specificity would be (0,0,0,1) or 1 for both. Thus, the specificity is equal. In that case, the browser would pick the one that comes later.
p { font-family: Helvetica, sans-serif; color: blue; } p { border: thick solid green; font-family: Helvetica, sans-serif; color: green; }
If we load the file, then we would find that the browser has indeed picked up the later style.
The next rule for figuring out what is important is to look at the CSS source and the "!important" mandate specified in the style. The "!important" mandate is basically an instruction to the browser to ignore everything else and just follow the one specified with the "!important" keyword. Think of this keyword as a toddler throwing a tantrum and crying hard -- you would like to de-prioritize everything else and listen to the kid!
On a higher-level, the browser, in fact, picks up the declaration of the source based on the following preference (listed from highest order to the lowest order): (1) user agent CSS, (2) normal (with no !important keyword) declarations in user style CSS, (3) normal (with no !important keyword) declarations in author style CSS, (4) Important ((with the !important keyword) declarations in author CSS, and (5) Important (with the !important keyword) declarations in user style sheets.
To see the !important keyword in action, let us take the example from the earlier section and throw this keyword to declarations with lower-specificity. Normally, the browser would pick up the rule with the highest specificity, but with the !important keyword it would be forced to select the one that may or not have the highest specificity. Here is the HTML example.
<!doctype html> <html> <head> <title> Learning CSS: Cascade (Using !important Keyword) </title> <link type="text/css" rel="stylesheet" href="cascade_important.css"> </head> <body> <p id="id_mesozoic" class="class_mesozoic">The Mighty T-Rex: <br> Tyrannosaurus were carnivorous dinosaurs that lived during the late Cretaceous period. They were bipedal reptiles with a massive skull that was balanced by a long and heavy tail. Among them, the mightiest and the deadliest were the Tyrannosaurus rex (or T. rex for short). These giants could grow up to 40 feet in length, up to 20 feet in height, and weighed around 7 tons. </p> </body> </html>
For the corresponding CSS file ("cascade_important.css"), we throw the !important keyword with declarations from the ".class_mesozoic" and the "p.class_mesozoic" rules. Even though these do not have the highest specificity, the browser is compelled to use them.
/* Specificity: (0,0,0,1) or 1*/ p { font-family: Helvetica, sans-serif; color: blue; } /* Specificity: (0,0,1,1) or 11 */ p.class_mesozoic { border: thick dashed red !important; font-family: Helvetica, sans-serif; color: red; } /* Specificity: (0,1,0,1) or 101 */ p#id_mesozoic { border: thick solid green; font-family: Helvetica, sans-serif; color: green; } /* Specificity: (0,0,1,0) or 10 */ .class_mesozoic { border: thick dotted black; font-family: Helvetica, sans-serif; color: black !important; }
If we load the above file, then we would find that the browser has now picked up the styles specified using the !important instead of the ones specified in the "p#id_mesozoic" rule, which is the one with the highest specificity.
The above example shows the usage of the !important keyword with respect to specificity, but even in other cases (where for example, specificity is same), the !important keyword would still win. But, them with power, comes the responsibility. So, we should use !important only as a last resort. In a normal scenario, where we have well-designed CSS, we should be able to avoid using this keyword.