CSS Cascade

Damaris Göbel
5 min readMay 3, 2021

How browsers resolve competing style

Have you looked at a developer tools in the style and wonder why so much style is crossed out and not applied? I definitely wondered.

CSS stands for Cascading Style Sheets. It occurred to me a lot that my CSS didn’t work and I was tempted to just throw a !important after my CSS style to get it been applied.

Photo by Deleece Cook on Unsplash

The CSS Cascade is the way our browsers resolve competing CSS declarations.

Every time you write a CSS declaration, it will enter the CSS Cascade, which will determine whether or not it will end up as the final style.

The further down the cascade the less likely it will show up in the final style.

The cascade is basically an algorithm that defines how to combine property values originating from different sources.

Only CSS declarations, that is property/value pairs, participate in the cascade.

1. Importance

The first tier of the Cascade looks at these four basic types of rules:

  1. transition

(for all of you who wonders … transitions allows you to change property values smoothly, over a given duration.)

Rules that apply to an active transition take the utmost importance.

2. !important

By adding !important to the end of our declaration, it jumps to this level of the cascade. Ideally, you reserve this level for anything overriding styles from third-party libraries.

3. animation

(CSS allows animation of HTML elements without using JavaScript or Flash.)

Rules that apply to an active animation jump up a level in the cascade

4. normal

This level is where the bulk of rules live, basically all the other CSS styling.

Which of these two rules would win?

Example A

p {
color: sandybrown;
}

Example B

p {

color: orchid !important;

}

Example B would win! Remember that !important declarations fall on the second level, while normal declarations fall on the fourth level.

2. Origin

The second tier of the Cascade looks at where the rule was defined.

CSS declarations originate from different origins: the user-agent stylesheets, the Author stylesheets and the User stylesheets.

  1. Website

This is the only level that you have control over, as a web developer. It is also referred as author stylesheets.

2. User

This is the user stylesheet. Any user can override styles in many browsers.

3. Browser
Each browser has its own set of styles, which is why things like <button> have default styles. Any styles set by the browser are called user-agent stylesheets.

In the following example we have a user agent style sheet, two author style sheets, a user stylesheet, and inline styles within the HTML.

User-agent CSS:

li {
margin-left: 10px
}

Author CSS 1:

li {
margin-left: 0
}

Author CSS 2:

@media screen {
li { margin-left: 3px }
}

@media print {
li { margin-left: 1px }
}

User CSS:

.specific {
margin-left: 1em
}

HTML:

<ul>
<li class=”specific”>1<sup>st</sup></li>
<li>2<sup>nd</sup></li>
</ul>

What will be the CSS style of the list item?

In this case, declarations inside li and .specific rules should apply. No declaration is marked as !important, so the precedence order is author style sheets before user style sheets or user-agent stylesheet.

As it is screen and the author style sheet, Author CSS 2 with margin-left: 3px wins!

3. Specificity

The third tier of the cascade looks at the specificity of a rule.

There are four levels of selectors:

1. inline

Styles declared within a style HTML property are the most specific. When we create a CSS declaration, we can target specific elements using selectors.

2. id

We can target elements based on their id, using the syntax #id

3. class | attribute | pseudo-class

We can target elements based on their class, using the syntax .class. This level also includes attribute selectors that target HTML attributes, like [checked] and [href=”https://www.google.com"]. And this level also includes pseudo-selectors, like :hover and :first-of-type

4. type | pseudo-element

We can target elements based on their tag type, using the syntax type. This level also includes pseudo-elements, like :before and :selection

Example A *.html

<p style=”color: sandybrown”>…</p>

Example B *.css

p {

color: orchid;

}

Example A wins! Remember that inline styles fall on the first level, while type rules fall on the fourth level.

Who wins here?

Example A

.paragraph {

color: sandybrown;

}

Example B

#paragraph {

color: orchid;

}

Example B wins! Remember that rules with a class selector fall on the third level, while rules with an id selector fall on the second level.

Who wins here?

Example A

.paragraph:first-of-type {

color: sandybrown;

}

Example B

p.paragraph {

color: orchid;

}

Example A wins!

Example A has two “hits” on the third level (1 class and 1 pseudo-class), whereas Example B has only one “hit” on the third level — its “hit” on a lower (fourth) level doesn’t come into play.

Additionally, on this tier of the cascade, ties can be broken within this tier. This means that, if two rules have the same number of hits on their highest level, one can win by having a hit on the next level down.

Example A

p#paragraph {

color: sandybrown;

}

Example B

#paragraph.paragraph {

color: orchid;

}

Example A and B both have 1 hit on the second level (1 id), but Example B additionally has 1 hit on the third level (1 class), which beats Example A’s hit on the fourth level (1 tag). Example B wins!

4. Position

This tier of the cascade looks at the order that the rules were defined in.

When two selectors have the same specificity, the declaration that comes last in the source code wins. If you’ve got two stylesheets linked in the head of your HTML document, the second stylesheet will override rules in the first stylesheet.

If you are using a CSS framework you will want to load your custom styles afterwards.

One last question:

.red {color: red;}.blue {color: blue;}

Which color would these divs be?

<div class="red blue"><div class="blue red">

The correct answer: they’re both blue, because that’s the last one that’s defined in the stylesheet.

Last rules to remember:

· Classes are more specific than element selectors like p, h1

· IDs are more specific than classes.

· Combined selectors are more specific than single selectors.

· Inline styles are more specific than stuff in stylesheets.

I hope you learnt sth. and you are not more confused than before.

Try to practice these best practices:

  • Use as little specificity as possible. Try to use element and class selectors over IDs and combination selectors. Avoid inline styles whenever possible.
  • Structure your code according to the cascade. Put general element-based styles up top, followed by specific component styles, followed by modifiers.

More resources: https://drafts.csswg.org/css-cascade/

--

--

Damaris Göbel

I like to do crazy things with CSS & JavaScript. My brain occasionally runs out of memory so I need to write down my thoughts.