Following up from Geoff’s intro article on The Second “S” in CSS, let’s now move the spotlight to the “C” in CSS — what we call the Cascade. It’s where things start to get messy, and even confusing at times.
Have you ever written a CSS property and the value doesn’t seem to work? Maybe you had to turn to using !important
to get it going. Or perhaps you resorted to writing the CSS inline on the element in the HTML file.
<div style="background:orange; height:100px; width:100px;">
Ack, inline!
</div>
Speaking of inline styles, have you wondered why SVG editors use them instead of a separate CSS file? That seems kinda weird, right?
<svg id="icon-logo-star" viewBox="0 0 362.62 388.52" width="100%" height="100%">
<style>
.logo {
fill: #ff9800;
}
</style>
<title>CSS Tricks Logo</title>
<path class="logo" d="M156.58 239l-88.3 64.75c-10.59 7.06-18.84 11.77-29.43 11.77-21.19 0-38.85-18.84-38.85-40 0-17.69 14.13-30.64 27.08-36.52l103.6-44.74-103.6-45.92C13 142.46 0 129.51 0 111.85 0 90.66 18.84 73 40 73c10.6 0 17.66 3.53 28.25 11.77l88.3 64.75-11.74-104.78C141.28 20 157.76 0 181.31 0s40 18.84 36.5 43.56L206 149.52l88.3-64.75C304.93 76.53 313.17 73 323.77 73a39.2 39.2 0 0 1 38.85 38.85c0 18.84-12.95 30.61-27.08 36.5l-103.61 45.91L335.54 239c14.13 5.88 27.08 18.83 27.08 37.67 0 21.19-18.84 38.85-40 38.85-9.42 0-17.66-4.71-28.26-11.77L206 239l11.77 104.78c3.53 24.72-12.95 44.74-36.5 44.74s-40-18.84-36.5-43.56z"></path>
</svg>
Well, the cascade has a lot to do with this. Read on to find out how styling methods affect what’s being applied to your elements and how to use the cascade to your advantage because, believe me, it’s a wonderful thing when you get the hang of it.
TL;DR: Jump right to the CSS order diagram for a visual of how everything works.
The cascade cares about how and where styles are written
There are a myriad of ways you can apply CSS rules to an element. Below is an example of how stroke: red;
can be applied to the same element. The examples are ordered in ascending priority, where the highest priority is at the bottom:
<!-- Inheritance -->
<g style="stroke: red">
<rect x="1" y="1" width="10" height="10" /> <!-- inherits stroke: red -->
</g>
<!-- Inline attributes -->
<rect x="1" y="1" width="10" height="10" stroke="red" />
<!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css">
<!-- Embedded styles -->
<style>
rect { stroke: red; }
</style>
<!-- Different specificity or selectors -->
rect { stroke: red; }
.myClass { stroke: red; }
#myID { stroke: red; }
<!-- Inline style -->
<g style="stroke: red"></g>
<!-- Important keyword -->
<g style="stroke: red !important"></g>
Inheritance? Embedded? External? Inline? Specificity? Important? Yeah, lots of terms being thrown around. Let’s break those down a bit because each one determines what the browser ends up using when a web page loads.
Elements can inherit styles from other elements
Both HTML and SVG elements can inherit CSS rules that are applied to other elements. We call this a parent-child relationship, where the element the CSS is applied to is the parent and the element contained inside the parent is the child.
<div class="parent">
<div class="child">I'm the child because the parent is wrapped around me.</div>
</div>
If we set the text color of the parent and do not declare a text color on the child, then the child will look up to the parent to know what color its text should be. We call that inheritance and it’s a prime example of how a style cascades down to an element it matches… or “bubbles up” the chain to the next matched style.
However, inheritance has the lowest priority among styling methods. In other words, if a child has a rule that is specific to it, then the inherited value will be ignored, even though the inherited value may have an important keyword. The following is an example:
<div class="parent" style="color: red !important;">
<div class="child">I'm the child because the parent is wrapped around me.</div>
</div>
See the Pen Child ignores inline inheritance with !important by Geoff Graham (@geoffgraham) on CodePen.
SVG inline attributes
For SVG elements, we can also apply styles using inline attributes, where those have the second lowest priority in the cascade. This means the CSS rules in a stylesheet will be able to override them.
<rect x="1" y="1" width="10" height="10" stroke="red" />
rect {
stroke: blue;
}
See the Pen Stylesheet overrides SVG inline attributes by Geoff Graham (@geoffgraham) on CodePen.
Most SVG editors use inline attributes for portability; that is, the ability to copy some elements and paste them elsewhere without losing the attributes. Users can then use the resultant SVG and style its elements using an external stylesheet.
Stylesheets
Stylesheets are divided into two flavors: external and embedded:
<!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css">
<!-- Embedded styles -->
<style>
div { border: 1px solid red }
</style>
Embedded styles have the same priority as external stylesheets. Therefore, if you have the same CSS rules, ordering rules applies.
See the Pen Embedded styles override stylesheet rules by Geoff Graham (@geoffgraham) on CodePen.
All stylesheets follow ordering rules, where files that are defined later, will have higher priority than those defined earlier. In this example, stylesheet-2.css
will take precedence over the stylesheet-1.css
file because it is defined last.
<link rel="stylesheet" href="/path/to/stylesheet-1.css">
<link rel="stylesheet" href="/path/to/stylesheet-2.css">
Specificity or selectors
How you select your elements will also determine which rules are applied, whereby tags (e.g. <p>
, <div>
), classes (e.g. .my-class
) and IDs (e.g. #myI-id
) have ascending priorities.
See the Pen Specificity by selectors by Geoff Graham (@geoffgraham) on CodePen.
In the example above, if you have a div element with both .my-class
and #my-id
, the border will be red because IDs have higher priority than classes and tags.
*Specificity has higher priority than ordering rules, therefore, irrespective if your rule is at the top or bottom. Specificity still has higher priority and will be applied.
Ordering
CSS rules always prioritize from left-to-right, then from top-to-bottom.
<!-- Blue will be applied because it is on the right -->
<div style="border: 1px solid red; border: 1px solid blue;"></div>
<style>
div {
border: 1px solid red;
border: 1px solid blue; /* This will be applied because it is at the bottom */
}
</style>
Inline styles
Inline styles have the second highest priority, just below the !important
keyword. This means that inline styles are only overridden by the important keyword and nothing else. Within inline styles, normal ordering rules applies, from left-to-right and top-to-bottom.
<div style="1px solid red;"></div>
The important keyword
Speaking of the !important
keyword, it is used to override ordering, specificity and inline rules. In other words, it wields incredible powers.
Overriding inline rules
<style>
div {
/* This beats inline styling */
border: 1px solid orange !important;
/* These do not */
height: 200px;
width: 200px;
}
</style>
<div style="border: 1px solid red; height: 100px; width: 100px;"></div>
In the example above, without the important keyword, the div would have a red border because inline styling has higher priority than embedded styles. But, with the important keyword, the div border becomes orange, because the important keyword has higher priority than inline styling.
Using !important
can be super useful, but should be used with caution. Chris has some thoughts on situations where it makes sense to use it.
Overriding specificity rules
Without the important keyword, this div border will be blue, because classes have higher priority than tags in specificity.
<style>
/* Classes have higher priority than tags */
.my-class {
border: 1px solid blue;
height: 100px;
width: 100px;
}
div {
border: 1px solid red;
height: 200px;
width: 200px;
}
</style>
<div class="my-class"></div>
See the Pen Classes beat tags by Geoff Graham (@geoffgraham) on CodePen.
But! Adding the important keyword to the tag rules tells the element to ignore the cascade and take precedence over the class rules.
<style>
.my-class { border: 1px solid red; }
/* The important keyword overrides specificity priority */
.my-class { border: 1px solid blue !important; }
</style>
<div class="my-class"></div>
See the Pen !important ignores the cascade by Geoff Graham (@geoffgraham) on CodePen.
Overriding ordering rules
OK, so we’ve already talked about how the order of rules affects specificity: bottom beats top and right beats left. The surefire way to override that is to put !important
into use once again.
In this example, the div will take the red border, even though the blue border is the bottom rule. You can thank !important
for that handiwork.
<style>
div { border: 1px solid red !important; } /* This wins, despite the ordering */
div { border: 1px solid blue; }
</style>
<div></div>
See the Pen Important wins over ordering by Geoff Graham (@geoffgraham) on CodePen.
Visualizing the cascade
Who knew there was so much meaning in the “C” of CSS? We covered a ton of ground here and hopefully it helps clarify the way styles are affected and applied by how we write them. The cascade is a powerful feature. There are opinions galore about how to use it properly, but you can see the various ways properties are passed and inherited by elements.
More of a visual learner? Here’s a chart that pulls it all together.
Thomas, thank you for the beautiful visual guide to CSS cascade. Unfortunately, your article and this chart are not completely technically correct: the claim that embedded styles always override the linked styles is wrong. The CSS Cascading and Inheritance spec doesn’t distinguish these, instead it treats it as the same Cascading Origin (Author Origin) and effectively says that linked styles are replaces with the equivalent embedded styles when calculating precedence (“Declarations from style sheets independently linked by the originating document are treated as if they were concatenated in linking order”). And among the styles from the same Origin and with the same specificity only the resulting declaration order matters.
In your Codepen demo, there are actually two embedded stylesheets — one in
<head>
and one in<body>
(at least, it’s what I see there in the DOM inspector), and the latter wins over the former only because of the order. Hovewer, if you add the link to the same styles as the external resource after the last embedded stylesheet, these external styles would override it, as in this fork of your Codepen: https://codepen.io/SelenIT/pen/pQRGEv@Ilya, Thanks a million for pointing out that mistake. I will amend the article and also the diagram accordingly, much appreciated!
I’m very confused by this precedence of right over left. Your examples are incomplete as far as I can tell: style=”1px solid red” doesn’t do anything. Could you be more precise?
Or is it just because it is defined “after” the previous one? and thus on the right of the previous definition? This is not priority to the right, this is coding order…
@Ben, Thanks for the heads up, the correct example should be:
<div style=”border: 1px solid red; border: 1px solid blue;”>
In simple words, if you have 2 rules that applies to the same element, the rule that is on the right or bottom will apply due to ordering rules. Hopes that helps.
I was wondering which kind of properties are inherited in CSS while reading this post, and which are not. It appears that it’s not easy to even get a list of all inherited properties, and it seems there is no clear/logical rules. I think it might be not so easy for a CSS beginner to guess which of them are inherited or not, without having to go on MDN or some other kind of reference.
@Guillaume, unfortunately that is correct but that sounds like a good opportunity to make a diagram for easy reference, and we love diagrams :) Let me see what I can do.
Hi Thomas, I finally found a way to list those values. Long story short: I ran a fetch request from the Chromium site, via its search form endpoint. You can find the script here: https://gist.github.com/cdoublev/1a5c4498adde3c6e775de5f0327dead4. I edited my Google Sheet used as a personal CSS convention to order CSS properties: https://docs.google.com/spreadsheets/d/1JIeXks17Wuad_wtDCoB–GOl1RwBQX7VP1IEd-iDHgo/. The labels I used to group properties may be semantically incorrect but I don’t think any nomenclature actually exists. Feel free to use it for your own research (a sheet might be a good option for diagrams).
Note: deprecated properties were voluntary dismissed in my sheet.
Some inherited properties were missing with this method. That’s why I finally gave up and manually checked all of them on MDN… It appeared that almost all of them were inherited shorthand properties. But it was a better option than trying with MDN or W3C. Neither offers an API. It would have been a real pain to parse HTML to fetch the inheritance value of each property. Furthermore, some properties are missing in their respective reference list: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference and https://www.w3.org/TR/CSS/#properties.
Thanks a million @Guillaume , that is a very impressive work. Thank you so much for sharing it with us. We shall see how we can convert these information into a diagram, will be sharing a draft to you before finalizing it. Mind sending me your email address at [email protected] ? Thanks!