3 min read

The Cascade

In your initial lesson about CSS, you learned that CSS stands for Cascading StyleSheets and that

…the cascade refers to the order and importance of your style rules. Once you’ve practiced some basic CSS, we’ll revisit the cascade and you’ll explore some examples of why it’s important.

This poetic word – the cascade – encompasses all the logic that determines how the styles you write are applied in the browser.

This intro to the cascade will not cover all its details, but it is helpful to understand some basics about the cascade in order to debug any CSS conflicts you may encounter. In this lesson, you’ll learn a bit about the cascade, including the weight and specificity of CSS selectors.

Order matters

The most basic thing to know about CSS is that the order in which you write your stylesheet has an impact on what happens in the browser.

The following CSS has conflicts because the color property is repeated for both the h1 and the h2 elements:

h1 {
  color: blue;
  color: purple;
}
h2 {
  color: purple;
}
h2 {
  color: red;
}

In the following demo, you can see how things get resolved:

Since a CSS file is read from top to bottom, in general, later declarations overwrite earlier ones; simply stated: what’s last, wins.

💡 You can hopefully avoid this issue by:

  • Organizing your CSS properties alphabetically within each ruleset.
  • Organizing your CSS selectors with a logical structure.

Selectors have weight

In the previous example, all the CSS selectors were base HTML elements. This, however, is only one way you can select elements. For example, you can also select an element based on an ID or class selector:

<p id="special" class="demo">Lorem ipsum...</p>

The following demo uses the HTML above and this CSS:

#special {
  background-color: silver;
}

.demo {
  background-color: red;
}

p {
  background-color: purple;
  color: white;
}

Despite the fact that the last background-color declaration has a value of purple, it still doesn’t win? 🤷🏻‍♀️ What gives?

Here, the issue is that the selectors used have a different weight; the cascade considers how generic a selector is as part of its calculations.

  • a base element, like p, selects all elements of that type in the document and is very generic
  • a class name (.demo) only selects elements with a matching class and is less generic
  • an ID (#special) should be unique and, therefore, can only apply to one element on a page

Because of its uniqueness, the ID selector wins out against these other selectors, regardless of its location in the stylesheet.

💡 You can hopefully avoid this issue by:

  • Organizing your stylesheet so all your base element selectors are first, followed by your class selectors
  • Avoiding using ID selectors

Conflicts overwrite

When there are CSS conflicts, it’s important to note that the “losing” declarations are overwritten, not ignored.

You can see this in your browser developer tools. In the example below, you will see in the bottom right corner that all three background-color declarations are visible, and the losing declarations are grey and crossed out.

Screenshot of the Glitch project above with developer tools visible and the CSS conflicts highlighted.

Also, note that conflicts are resolved on a declaration-by-declaration basis. Just because the background-color declaration on the p selector is overwritten does not mean the color declaration within the same ruleset also gets overwritten; since there are no conflicts with the color declaration, it is applied as written.

This is a pretty cool thing about writing CSS. Instead of treating such conflicts as errors that break stylesheets, they are accounted for in the browser logic.

This also extends to CSS that is actually broken or invalid, not just conflicts. It’s rare to write CSS that totally breaks your stylesheet; instead, it’s often just a single declaration that fails.

Selectors have specificity

You’ve already learned that CSS files are read top to bottom, but you should also know that selectors are read from right to left.

This means the selector header h1 a applies to:

  • any a element
  • that is inside an h1 element
  • that is inside a header element

Referring to multiple elements or class names increases the specificity of the selector. Given the following CSS:

header h1 a {
  color: red;
}
a {
  color: green;
}

Any a element inside a h1 that is inside a header will be red, even though the color: green declaration is later in the stylesheet; you can see this result in the following demo:

💡 You can hopefully avoid this issue by:

  • Not writing your CSS selectors to reflect your nested HTML structure and instead using classnames
  • In general, avoiding using more than two selectors for a single ruleset

Share What You've Learned

Open in a new window

Make this page better.

Found something that's incorrect or confusing on this page? Broken link? I want to know! Open an issue on GitHub to tell me what's up and help me update the page.