Understanding The CSS Cascade: The Engine That Makes It All Work
Tapha Ngum
Published: 2021-08-19
CSS cascade exampleCSS cascade meaningwhat is the CSS cascade(This article was originally published in How To Debug CSS)
A lot of what makes CSS hard to understand is the simple fact that most of the concepts that underpin it, are rarely understood by developers in any real depth.
A lot of the reason for this comes down to the fact that CSS ‘feels’ like, it ‘should be’ easy.
In short, developers, in general, don’t take it very seriously.
This leads to a ‘jenga‘ style of learning CSS, that leaves many gaps in your overall knowledge over time. Which then leads to you struggling with something that should seem simple, but that many developers find, is not really that simple at all.
One of the most fundamental concepts that most developers skip over in CSS is the Cascade.
It is a key part of CSS, which when properly understood, lays the foundation for a proper understanding (and ultimately better usage) of CSS.
WHAT THE CASCADE IS
The CSS specificity ‘engine’, or what is commonly known as the ‘cascade’, is what determines which CSS style declarations ‘win’, or in other words, which style declarations are more likely to get shown than other style declarations within an overall HTML page structure.
As we can see in the drawing above, it is the ‘inline’ style that holds the most power and gets shown if competing with the style declarations at the other levels of the cascade.
The above cascade example shows us how the cascade decides what style declarations are more important at the high level (outside of a CSS file).
But how does it determine which style declarations are more important within a document?
There are two ways that the Cascade determines this (in order):
- (Position within document) – By where a style declaration takes place in the overall document flow (both the HTML and the CSS documents). The cascade engine then reads through the document(s) from top-to-bottom, and gives greater specificity to the bottom-most style declaration. So whichever comes last. Sidenote: According to the cascade, inline styles within HTML documents are the bottom-most style declarations positionally (they are below all the other ways that we can declare styles).
- (Selector weighting) – By weighting (from 0-100) the selectors (within a stylesheet) used on a declaration and determining by this weighting which selector declarations has the most specificity.
The 1st way (positionally within a document) is what the cascade looks at first, and is relatively straightforward.
Once the Cascade has determined which declarations are the most important, whether they be internal styles or in a separate stylesheet, the 2nd way is triggered. This is the last part of the cascades decision making system.
(* inline styles don’t really fall into the 2nd way, as they are already the most powerful, and don’t need selectors, as they are inline. Rated number one!)
The 2nd way (by selector weighting) is a little more complicated.
Let’s shed some light on how this selector weighting that the Cascade does within stylesheets, works.
(* Don’t worry about remembering how the cascade weights style declarations off head. As you work with CSS, and review helpful reference materials like the example drawing, it will gradually start to become intuitive to you.)
HOW THE CASCADE SELECTOR WEIGHTING WORKS
Once the Cascade has determined which styles it will prioritise, it moves onto seeing which of the actual declarations in the order of execution should come first.
The way it does this is by weighing the selectors of the declarations, to see which of its corresponding declarations has the most power.
The above diagram gives us a basic idea of how this weighting is done. But it only tells us about individual selectors.
What happens when these selectors are combined ?
The individual selectors can, of course, be combined, as we learned in the ‘combinators’ section from the previous chapter.
With the Cascade, the weighting that results thereof will be the sum total of the combined selector’s individual weightings.
But how does CSS weigh these individual selectors?
When we we want to get the sum of two numbers, we first need to know what those numbers are.
In the same way, to know what the eventual weighting of a selector combination is, we should first break down each of our individual selectors to a numerical value, then we can just add them up to get their overall weighting when combined.
This is what the Cascade does naturally, under the hood. It is literally just a calculator.
The selector or selector combination with the highest overall weighting ‘score’ is the one that has the most specificity and the one that will ultimately be used by the cascade to style the element.
So what are the numerical values that the Cascade assigns to individual selectors?
Let’s take a look.
As you can see, the Cascade gives each selector a numerical ‘points’ value.
With the Inline styles scoring 1,000 points.
The ID’s scoring 100 points.
Classes, Attributes and Pseudo-Classes scoring 10 points each.
And Elements and Pseudo-Elements scoring 1 point each.
Whether combined or used as individual selectors, the total added sum of the selector ‘point’ values is what determines the final weight of the style declaration within the Cascade.
For example, what score would you give this style declaration:
#special p {}
The answer is 101.
With ‘#special’ ID scoring 100, and ‘p’ HTML element tag scoring 1.
Bonus: There is one CSS value that can be used within a declaration that can override all other specificity and give a declaration the highest level of specificity, no matter where it sits on the cascade hierarchy, and that value is ‘!important’. By placing !important at the end of your property: value statement within your style declaration, you can make that declaration ‘force’ itself into being at the highest level of specificity. Usually, it is not a good idea to use it, and its use is an indicator that you may have poorly structured your code.
Example:
HTML
<p>
This is important.
</p>
CSS
p {
color: red !important;
}
p {
color: blue;
}
(code for this here: https://codepen.io/planflowdev/pen/VwmGeJW)
In this case, even though the ‘color: blue;’ declaration is the ‘bottom-most’ declaration, and therefore should be the one the Cascade selects, because ‘!important’ is applied to the declaration above it, that is the one that wins.
!important overrides the Cascade, and forces a style rule to win.
(* Again, don’t try to memorize the specificity scores. You WILL forget. Just keep going through the exercises and practicing, it will eventually start to become more intuitive to you. TRUST the process!)
SUMMARY VIEW – HOW TO RUN THE CASCADE IN YOUR OWN MIND
To understand overall how an element’s style declaration will be weighted by the cascade, you should try to think like the cascade thinks.
Remember that the goal of the cascade is to find out what the most specific styles are.
So when trying to determine this, first ask where the style is defined, and give that a weight.
Once you’ve done that, assuming the first question did not already give the style a maximum weighting (if it is an inline style) then ask, in what order the style is placed. Remember that the bottom-most wins.
Lastly, look at the specificity of the selectors used and their weightings.
Determine whether your selector or selector combination has the highest weighting overall.
This will tell you what the specificity of your declaration is, and whether or not it will render despite any competition.
Because there are many different ways in which we can define the exact same styles, and 3 different locations in which we can place them, conflicts do occur.
When trying to apply styles to the same element in different ways, CSS must determine the order of what matters (which styles ultimately get rendered) and what doesn’t (which do not get rendered).
The Cascade works by determining this order.
--
Check out the easiest way to plan your website or mobile app. Try PlanFlow for free.