The “C” in CSS
๐ก
Essential Question: How does the Cascade affect how styles are applied to HTML elements?
OK, so we’ve established that CSS stands for Cascading Style Sheets. But what does it mean for style sheets to Cascade? It’s more than a popular brand of dish soap.
Introducing the Cascade
Let’s say we have the following HTML:
<div class="my-element">
<p>It's not denial. I'm just selective about the reality I accept.</p>
</div>
And let’s say we have the following CSS to style that paragraph of text:
p {
color: red;
}
.my-element p {
color: blue;
}
The “winning” color is blue because it has the highest specificity. Because the paragraph exists inside of the .my-element div, it will respect any color property values declared there before it goes looking for another option.
Let’s switch things up a bit.
<div class="another-element">
<p>It's not denial. I'm just selective about the reality I accept.</p>
</div>
The paragraph will be red in this case. That’s because there is no color declaration on the .another-element
div, so the element looks for the next color option that matches paragraphs, which is red.
The Cascade is a powerful tool. It’s also a thorn in the side if it is used improperly. In fact, it’s often the reason CSS gets a bad rep for being difficult, which has spurred dozens of memes like this:
โ ๏ธ Auto-Playing Media
We don’t want to end up like that, so let’s start with a basic cascade definition.
The Cascade is how the browser resolves competing CSS declarations.
You can think of the cascade as a waterfall. At the top are the most “important” values that are most likely to be used on an element. At the bottom are declarations that are less likely to be used.
There are different “tiers” to the waterfall. Let’s look at them one by one.
Importance
The first tier looks at the type of rules that are being used. Those types include:
- Transition: Any active transitions are at the top of the tier. That ensures anything that is in the progress of changing values (e.g. transitioning background colors) completes without interruption.
- !important: Adding this keyword at the end of a declaration (e.g.
color: red !important;
) bumps that declaration up to this top level, no matter where it is in the Cascade. Sort of like letting someone cut in line. It’s tempting to reach for this when something doesn’t seem to be working, but there are plenty of reasons to avoid using!important
to keep the Cascade intact. - Animation: Like transitions, any CSS animation that is running gets a bump in the Cascade.
Origin
Next up, the Cascade cares about where a CSS declaration is made, and that generally can be from three places:
- Website Styles: This is the current website reading the styles you wrote.
- User Styles: Did you know that you have a personal stylesheet when you use a browser? Well, you do, and you can find specific instructions for Chrome, Firefox, and Safari.
- Browser Styles: Browsers have their own stylesheets that provide default styles in the event that no styles are declared for the. The
<button>
element is a perfect example of this, as well as form inputs.
Specificity
This is where most of the cascading action takes place in CSS. It’s also where most of the confusion is. In short, specificity is how the browser “weighs” one style against another to see which one is used. Stated differently, specificity adds weight to a style based on the type of selector being used.
Those selectors include:
- Inline: These are any styles that are declared inside a
<style>
attribute directly in an HTML document. They are given the greatest weight of any selector, meaning it becomes difficult to override these styles in your stylesheet since they are embedded directly in the HTML. - ID: The ID (e.g.
#myElement
) of an element will always win over a class. Speaking of which… - Class: We can select elements by their class (e.g.
.my-element
). Alongside classes are attributes (e.g.[data-type="button"]
) and pseudo-selectors (e.g.:hover
) which share the same level of specificity. - Type: The “type” refers to styles applied directly to a type of element. For example, we can define styles for all paragraphs just by declaring them on the
<p>
element (i.e.p { color: red; }
). This also includes pseudo-elements (e.g.::before
and::after
), which we will cover in an upcoming module.
Quick! Which of these rules wins the color fight?
This one in HTML:
<p style="color: red;">...</p>
…or this one in a CSS file:
p { color: blue; }
Show the answer The HTML rule wins because the styles are inline directly in the HTML, where the CSS file has a lower specificity.
Position
At the bottom of the cascade is the position (or order) in which a style is declared. Consider the following poorly written code:
p {
color: red;
color: blue;
}
Blue wins in this example because it is declared “last” in the ruleset. We could bump red up in the cascade if we appended !important
to it, but again, there’s very little incentive to do this. It makes more sense to remove the unnecessary style and let the Cascade do its thing.
This is the clearest example of how the cascade works. It starts at the bottom position, then “bubbles up” until it finds the next matching declaration it can use.
โถ๏ธ Video: CSS Specificity Explained
In the following video, Kevin Powell breaks down the cascade even further by discussing how the cascade uses specificity to determine what styles are applied to matched elements. Take note of how he defines specificity and what it does. You should walk away from this video with an understanding of how specificity is calculated.
Check Your Understanding
Phew, that was a lot of information! Review the following questions to determine if you are ready to move on to the next unit.
(1) What color is the text in the following CSS snippet?
p {
color: black;
color: orange;
}
Show the Answer
The text will be orange because the CSS Cascade reads styles from the bottom to the top. If the same property is declared twice in the same CSS ruleset, the second property declaration wins because it comes last.
(2) Why is it a good idea to avoid using the !important
keyword with a CSS property?
Show the Answer
Using the keyword changes the Importance of the property in the CSS Cascade so that it takes precedence, even if it is not the most specific declaration. The Importance is so great when using the !important
that it is difficult to override it with other declared styles when you need to. Instead of using the keyword, use the natural behavior of the Cascade to make sure the correct styles are applied to your elements.