CSS: How does it cascade?

Orkhan Huseynli
4 min readAug 12, 2018

--

When I was new to web development I used to write some simple CSS but never wondered what does that acronym mean. After finding out that it means Cascading Style Sheets, i translated the word cascade to my native language (Azerbaijani) which didn’t really make sense, then stopped wondering about that word and totally forgot it. Until i decided to deep dive into CSS.

So, what does cascading mean and how does it cascade?

At some point in your code, you’ll find yourself in a situation where several CSS rules applied for an element. Be it a style coming from other style sheets like the CSS framework you’re using or your own declarations in other files or inline styles. So the browser needs to determine the winner style and apply it to the element in the end. This is controlled by the mechanism called Cascade.

To understand it let’s start from the beginning: What happens when you open a beautifully designed web page?

  • The browser starts to read the HTML code, parses it and creates Document Object Model (DOM).
  • It downloads any style sheets if it sees <link> tag, parses CSS code and creates CSS Object Model (CSSOM).
  • Then it combines DOM and CSSOM creating what is called Render Tree.
  • Then using the Render Tree as input, layout of each node is computed and overall layout is built.
  • And finally, each node is painted to the screen.

This is called Critical Rendering Path and here is how it looks like:

Critical Rendering Path

Since our topic is Cascade, we will focus on construction of CSSOM and how CSS is being parsed. So, in CSS parsing phase there are two main steps:

  1. Resolving conflicting CSS declarations. That’s when the cascading happens.
  2. Processing final CSS values. That’s when values like % , em and rem are converted to pixels and inherited values are obtained.

Now, let’s talk how conflicting CSS declarations are resolved and how the browser chooses the “winner” style that is applied on the element.

Which style wins in the cascade depends on three factors:

  1. Importance
  2. Specificity
  3. Source order

Note that the order here matters, the earlier ones will overrule later ones.

Importance

There is a special piece of syntax that you can use to make sure that a certain declaration will always win over all others: !important

A simple example would look like this:

h1 {
background-color: red !important;
}

In the above code, the background-color rule here will overrule any other background-color declarations on h1 element.

The only way to overrule an !important declaration is to include another !important declaration (with more specificity), and conflicting !important declarations will be applied in the following order (with later ones overriding earlier ones):

  1. Declarations in user agent style sheets (browser’s default styles)
  2. Normal declarations in user style sheets (custom styles set by user)
  3. Normal declarations in author style sheets (styles set by developer)
  4. Important declarations in author style sheets
  5. Important declarations in user style sheets

Specificity

Specificity defines how specific a selector is. For example using ID selector while styling has highest specificity (without inline styles), so the only way of overriding styles declared in ID selector is to use !important keyword.

The specificity of a selector is measured using four different values:

  1. Inline styles
  2. ID selectors
  3. Class, attribute, pseudo class selectors
  4. Element and pseudo element selectors

I believe that it is not clear. Consider following example:

/* 1st rule: specificity is 0010 */
.button {
font-size: 20px;
color: white;
background-color: blue;
}
/* 2nd rule: specificity is 0122 */
nav#nav div.pull-right .button {
background-color: green;
}
/* 3rd rule: specificity is 0001 */
a {
background-color: purple;
}
/* 4th rule: specificity is 0121 */
#nav a.button:hover {
background-color: yellow;
}

Each of those CSS rules are trying to apply some background-color to an HTML anchor tag. So, who is the winner if there is not an !important declaration?

Let’s assess each rule by four different values as we noted above:

  • The first rule gets 0 point for inline styling, 0 point for ID selector, 1 point for a class selector and 0 point for element and pseudo element selectors. So final value is 0010
  • The second rule gets 0 point for inline styling, 1 point for an ID selector, 2 points for class selectors and 2 points for element selectors. The final value is 0122
  • The third rule gets 0 point for inline styling, 0 point for ID selector, 0 point for class or pseudo class selectors and 1 point for an element selector. The final value is 0001
  • The fourth rule gets 0 point for inline styling, 1 point for an ID selector, 2 points for class and pseudo class selector and 1 point for an element selector. The final value is 0121

If we compare the final values we will see that our winner CSS rule will be the second rule here as it has the most specificity score among them. So background of the anchor button will be green.

Source order

If all competing CSS rules has the same importance and the same specificity the winner rule will be defined by the source order. So, the last rule written in the code will override the previous one. A simple example would be this:

p {
color: blue;
}

/* This rule will win over the first one */
p {
color: red;
}

No explanation is needed, I believe.

Conclusion

Understanding the mechanism of CSS cascading is very important since if you are a front-end web developer. I hope this article was helpful and next time when you say Cascading Style Sheets you will say it with more confidence :)

If you want to read and learn more about these concepts, please check out references section.

References

https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction

--

--

Responses (1)