Why Isn’t Your CSS Working? Understanding Cascading
CSS stands for Cascading Style Sheets. As the name suggests, a Style Sheet is a file used to style your web page. (Fun fact: the file extension for CSS is simply .css—just like its acronym with a dot in front!) With CSS, you can apply styles to elements on your webpage using CSS Selectors, which target HTML elements based on their attributes, classes, IDs, or other properties. CSS allows you to design beautiful websites and even animate elements to enhance user interaction. Now that we understand the “Style Sheet” part—short and crisp—let’s break down the Cascading aspect. This is Part Two of our “Why Isn’t Your CSS Working?” series. In the previous article, we explored specificity in depth. Now, it’s time to apply that knowledge to better understand cascading—and how both work together to determine which style rules win. I’ve explained cascading through an investigative, real-world approach—so it feels more practical and relatable, not just theory. Although cascading and specificity are theory-heavy topics, this approach will help you actually understand and apply them, rather than just memorize the rules. At the end of this article you'll get the opportunity to strenthen your know with a quiz - I also provided the answer and its explaination If you're already familiar with specificity, then you're good to go If not, I highly recommend checking out my previous article: Why Isn't Your CSS Working? Understanding Specificity Table of Contents The Cascade: Why Order Matters 1. Cascading Rule #1: Source Order (Last Rule Wins) 2. Cascading Rule #2: Higher Specificity Overrides Source Order 3. Cascading Rule #3: Importance of Rules 4. Cascading Rule #4: Origin of Styles 5. Contextual Importance: Inline Styles > All Difference Between Cascading and Specificity How Cascading and Specificity Both Are Soulmates Bottom line Quick Quiz: Strengthen Your Understanding of the Cascade Wrapping Up 12. SOLUTION OF THE QUIZ The Cascade: Why Order Matters Which color do you think will be applied to the .text class—red or blue? Let’s check the browser to see for ourselves: Wait, blue is applied—but what happened to red? To understand this, let’s inspect the element using the browser’s DevTools. I’m using Chrome DevTools. As you can see, the .text class with color: red; is crossed out, meaning the browser ignored it, and color: blue; is applied instead. And this brings us to: 1. Cascading Rule #1: Source Order (Last Rule Wins) If two rules have the same specificity targeting the same element, the one that appears later in the stylesheet will override the earlier one. How does this happen? Browsers read styles from top to bottom, so the last matching rule takes precedence. When two rules have the same specificity and target the same element with the same selector, the one that appears later will override the earlier one. The browser disregards the earlier rule because the later one takes priority during rendering. 2. Cascading Rule #2: Higher Specificity Overrides Source Order Even if a rule appears later in the stylesheet, it won’t win if an earlier rule has higher specificity. Let’s say you define a class selector after an ID selector—but both target the same element. The browser will still apply the ID rule because its specificity is stronger. Let’s check what the browser renders. Let’s inspect it using the browser’s DevTools: As you can see, the ID selector’s color red is applied, and the class selector’s blue is crossed out. That’s because ID selectors are more specific—even if they appear earlier in the CSS file. I used the color property here, but the same rule applies to any property—like background, font-size, and more. 3. Cascading Rule #3: Importance of Rules Now you know that the browser prioritizes the last rule when the specificity and selector are the same—and that higher specificity can override the last rule. However, there’s one more way to override both: by using !important. Let’s investigate it by checking the code, the browser, and DevTools—just like before. You can see how we used !important in our stylesheet. color: red; is applied instead of color: blue;. The .text class with color: blue; is crossed out and ignored by the browser. That’s the power of the !important keyword. -- Behind the Scenes When a rule is marked as !important, it gets higher priority than other rules with the same specificity—regardless of their position in the stylesheet. The browser internally flags this rule as more important and ensures it’s applied over all others. However, when multiple !important rules conflict, the browser still uses: Specificity (higher wins) Source order (last one wins) ...to decide which one takes effect. Let’s See Conflicting !important Rules in Action Specificity (Higher Wins) w Let’s select the same element u

CSS stands for Cascading Style Sheets. As the name suggests, a Style Sheet is a file used to style your web page. (Fun fact: the file extension for CSS is simply .css
—just like its acronym with a dot in front!)
With CSS, you can apply styles to elements on your webpage using CSS Selectors, which target HTML elements based on their attributes, classes, IDs, or other properties. CSS allows you to design beautiful websites and even animate elements to enhance user interaction.
Now that we understand the “Style Sheet” part—short and crisp—let’s break down the Cascading aspect.
This is Part Two of our “Why Isn’t Your CSS Working?” series. In the previous article, we explored specificity in depth. Now, it’s time to apply that knowledge to better understand cascading—and how both work together to determine which style rules win.
I’ve explained cascading through an investigative, real-world approach—so it feels more practical and relatable, not just theory.
Although cascading and specificity are theory-heavy topics, this approach will help you actually understand and apply them, rather than just memorize the rules. At the end of this article you'll get the opportunity to strenthen your know with a quiz - I also provided the answer and its explaination
If you're already familiar with specificity, then you're good to go
If not, I highly recommend checking out my previous article: Why Isn't Your CSS Working? Understanding Specificity
Table of Contents
- The Cascade: Why Order Matters
- 1. Cascading Rule #1: Source Order (Last Rule Wins)
- 2. Cascading Rule #2: Higher Specificity Overrides Source Order
- 3. Cascading Rule #3: Importance of Rules
- 4. Cascading Rule #4: Origin of Styles
- 5. Contextual Importance: Inline Styles > All
- Difference Between Cascading and Specificity
- How Cascading and Specificity Both Are Soulmates
- Bottom line
- Quick Quiz: Strengthen Your Understanding of the Cascade
- Wrapping Up
12. SOLUTION OF THE QUIZ
The Cascade: Why Order Matters
Which color do you think will be applied to the .text
class—red
or blue
?
Let’s check the browser to see for ourselves:
Wait, blue
is applied—but what happened to red
? To understand this, let’s inspect the element using the browser’s DevTools. I’m using Chrome DevTools.
As you can see, the .text
class with color: red;
is crossed out, meaning the browser ignored it, and color: blue;
is applied instead. And this brings us to:
1. Cascading Rule #1: Source Order (Last Rule Wins)
If two rules have the same specificity targeting the same element, the one that appears later in the stylesheet will override the earlier one.
How does this happen?
- Browsers read styles from top to bottom, so the last matching rule takes precedence.
- When two rules have the same specificity and target the same element with the same selector, the one that appears later will override the earlier one.
- The browser disregards the earlier rule because the later one takes priority during rendering.
2. Cascading Rule #2: Higher Specificity Overrides Source Order
Even if a rule appears later in the stylesheet, it won’t win if an earlier rule has higher specificity.
Let’s say you define a class selector after an ID selector—but both target the same element.
The browser will still apply the ID rule because its specificity is stronger.
Let’s check what the browser renders.
Let’s inspect it using the browser’s DevTools:
As you can see, the ID selector’s color red
is applied, and the class selector’s blue is crossed out.
That’s because ID selectors are more specific—even if they appear earlier in the CSS file.
I used the color
property here, but the same rule applies to any property—like background
, font-size
, and more.
3. Cascading Rule #3: Importance of Rules
Now you know that the browser prioritizes the last rule when the specificity and selector are the same—and that higher specificity can override the last rule.
However, there’s one more way to override both: by using !important
.
Let’s investigate it by checking the code, the browser, and DevTools—just like before.
You can see how we used !important
in our stylesheet.
color: red;
is applied instead of color: blue;
.
The .text
class with color: blue;
is crossed out and ignored by the browser.
That’s the power of the !important
keyword.
--
Behind the Scenes
When a rule is marked as !important
, it gets higher priority than other rules with the same specificity—regardless of their position in the stylesheet.
The browser internally flags this rule as more important and ensures it’s applied over all others.
However, when multiple !important
rules conflict, the browser still uses:
- Specificity (higher wins)
- Source order (last one wins)
...to decide which one takes effect.
Let’s See Conflicting !important
Rules in Action
Specificity (Higher Wins) w
Let’s select the same element using two class selectors and one ID selector—and mark all of them !important
.
Let’s see in the browser which one wins.
Now, let’s inspect the styles in DevTools and see what happened to the other rules.
After following along this far, you’ve probably already guessed it—the other rules have been crossed out.
Here, the browser applied the style based on specificity.
Although all rules had the !important
flag, the ID selector had the highest specificity, so its style (color: red;
) was applied.
Source Order (last one wins)
What happens if we comment out the rule with the ID selector? Let’s find out.
Let’s check the browser to see which rule gets applied.
Color green
is applied—now let’s inspect it in DevTools.
Oh! It’s source order at work—since the ID rule is commented out, the browser applied the last !important
rule it found. The earlier one was crossed out.
Pitfall: Don’t overuse
!important
, or debugging will become a nightmare!
Now that you have a solid understanding of source order, specificity, and importance, it’s time to move on to the next rule, which is:
4. Cascading Rule #4: Origin of Styles
I am going to show you one of the interesting things about the browser.
As you can see, I did not apply any style to the anchor tag, but it already comes with blue color and underline. But why?
Wait for a second — don’t think too much. I’ll explain it soon, but first, have a look at the image below:
Did you notice that?
a:-webkit-any-link {
color: -webkit-link;
cursor: pointer;
text-decoration: underline;
}
The browser styled it by itself — what we call user-agent (browser default) styles.
Styles can come from:
- the browser (user-agent styles),
- a user’s custom settings, or
- your CSS file (Author styles).
And usually, Author styles override user-agent styles.
Here’s an illustration:
As you see, I applied two properties that changed the color to purple and removed the underline.
Congratulations, it worked!
It overrode the user-agent styles — meaning the browser default styles — through my custom stylesheet. However, notice that it didn’t override cursor: pointer;
because I didn’t write any rule for cursor
, so the browser kept it.
That’s the full story on Cascading Rule #5: Origin of Styles.
When styles are defined by the Author, they override the user-agent styles because the specificity of Author styles is higher.
Note: Every browser has its own default style on elements, so different browsers style elements differently.
5. Contextual Importance: Inline Styles > All
Inline styles (e.g., style="color: red;"
directly on an element) are more specific than anything in your stylesheet — unless something in your stylesheet uses !important
and has higher specificity.
Let’s see it in action:
We used a combined ID and class selector for higher specificity, giving the color
property the value goldenrod
.
Now we defined inline CSS with the style
attribute and gave the value for the color
property as red
. Let’s check out the browser:
Inline CSS won because it has the highest specificity. Let’s inspect in DevTools:
Oh no! The combined ID and class selector:
#text_id.text {
color: goldenrod;
}
Lost to:
element.style {
color: red;
}
Which is inline CSS.
But here’s the catch — look at this:
We marked the CSS with the !important
keyword. Let’s see the result in the browser:
!important
overrode the inline CSS. Don’t believe me? Let’s check in DevTools:
The !important
rule overrides even the highest specificity like inline CSS — as I told you earlier in
3. Cascading Rule #3: Importance of Rules:
The browser internally flags this rule as more important and ensures it’s applied over all others.
No matter what the specificity is — if a rule is flagged with !important
, it wins.
However, by now you understand that inline CSS has the highest specificity among all — unless !important
steps in.
That’s the end of this article!
Just kidding haha!
I’m fully committed to helping you master CSS cascading rules. I won’t let you move on while you’re still confused — together, we’ll make sure you understand everything deeply and clearly.
In the previous part Why Isn't Your CSS Working? Understanding Specificity, I told you that Cascading and Specificity are soulmates.
But before we understand how, let’s first understand the difference between Cascading and Specificity.
Difference Between Cascading and Specificity
Both Cascading and Specificity help the browser decide which CSS rule to apply, but they play different roles in that decision:
-
Specificity is about how strongly a selector targets an element. Selectors with higher specificity override those with lower specificity.
- ID selectors have more specificity than class selectors.
- Class selectors are more specific than element selectors.
- Inline styles have the highest specificity (unless
!important
is used).
-
Cascading is the algorithm the browser uses when there are conflicting styles. It evaluates multiple factors in a specific order:
- Importance (
!important
) - Origin of styles (author, user, browser)
- Specificity
- Source order (last one wins)
- Importance (
In summary:
Specificity is just one piece of the Cascade puzzle.
When two rules conflict, the browser first checks for importance, then origin, then specificity, and finally source order to make the final decision.
How Cascading and Specificity Both Are Soulmates
You can't fully understand one without the other — that's why Cascading and Specificity are often called soulmates.
- Cascading provides the rules.
- Specificity provides the weight.
They work together to resolve conflicts and determine which CSS rule is the winner when multiple rules target the same element.
Think of Specificity as the "strength" of a rule and Cascading as the "judge" that decides which rule actually wins.
One sets the priority, and the other makes the final call.
Together, they ensure your styles behave as expected — or help you figure out why they don’t.
Why Are Media Queries Written at the End of a CSS File?
To understand why media queries (@media
) are typically placed at the end of a CSS file, let’s walk through a simple, real-world example. This will help us see how cascading and source order influence which styles get applied by the browser.
We’ll begin by writing a media query for screens with a maximum width of 400px and styling a element with the class
.text
.
When we open this in the browser on a desktop screen (width greater than 400px), the media query does not apply. So, we see no visible changes from the .text
class.
Inspecting the element in DevTools, we can see that the styles are coming from the body
tag and the universal selector *
.
Now let’s shrink the screen size below 400px. The media query condition is now true, so the styles inside the media query apply.
In DevTools, we can clearly see that the .text
class styles from the media query—background-color: white
and color: red
—are now active.
But what happens if we define the same .text
class again, outside of the media query, and after it in the CSS file?
Let’s look at the result on a desktop screen first.
Now let’s test it on a screen width below 400px, where the media query should apply.
Despite meeting the media query condition, the styles defined after the media query still apply. That’s because when two rules have the same specificity, the one that appears later in the stylesheet wins due to cascading and source order.
DevTools confirms this by showing that the media query styles are crossed out and overridden.
Now let’s update the media query and use an ID selector like #text
, which is more specific than the .text
class outside the media query.
This time, when the screen width is under 400px, the styles inside the media query take effect, despite being written earlier in the file.
DevTools shows that the ID-based styles are applied and the class-based styles are overridden.
When we return to desktop width, the ID selector condition no longer applies, so the .text
class styles are once again active.
And DevTools reflects this switch accurately.
From this, it becomes clear: even though media queries are conditional, they are still part of the CSS cascade. If a rule with the same specificity comes after a media query, it will override it—even if the media query condition is met.
That’s why it’s a best practice to write your media queries at the bottom of your CSS file. This way, they can override earlier styles and you don’t have to resort to unnecessarily increasing specificity.
Otherwise, your stylesheet becomes hard to manage as you constantly fight your own rules with repeated selectors.
So the conclusion is: we write media queries at the bottom so that the cascade works in our favor when using the same selectors with the same specificity.
Now that you understand how media queries and cascade order work together, here’s something to think about:
Why do we usually place the universal selector (*
) at the top of a CSS file?
You already know its specificity, and now you understand how cascade order works. Give it a thought. If you’re not sure, feel free to search or ask me.
Bottom line
This article explains how cascading works in CSS and how it interacts with specificity to determine which style rules are applied. Here's a summary of the key points:
Cascading Style Sheets (CSS) is used to style web pages through selectors that target HTML elements.
The Cascade is the algorithm browsers use to determine which CSS rules to apply when there are conflicts.
Cascading Rule #1: Source Order – When rules have the same specificity and target the same element, the last rule defined in the stylesheet wins.
Cascading Rule #2: Specificity – Rules with higher specificity override those with lower specificity, regardless of source order (ID selectors > class selectors > element selectors).
Cascading Rule #3: Importance – Rules marked with
!important
override normal rules regardless of specificity or source order.Cascading Rule #4: Origin of Styles – Styles can come from the browser (user-agent styles), user's custom settings, or author styles. Author styles typically override user-agent styles.
Cascading Rule #5: Inline Styles – Inline styles (written directly in the HTML) have higher specificity than styles in external stylesheets, unless overridden by
!important
.Relationship between Cascading and Specificity – Specificity is just one part of the cascade. The browser evaluates conflicts by checking importance, origin, specificity, and source order—in that order.
Media Queries and Source Order – Media queries are conditional, but they still participate in the cascade. If a rule with the same specificity appears after a media query, it can override the media query styles—even when the condition matches. That's why we usually write media queries at the bottom of our CSS files: so they have the final say when adapting styles for different screen sizes without needing to increase specificity.
When debugging CSS issues, browser DevTools are invaluable as they show which rules are being applied and which are being overridden.
Overusing
!important
can lead to maintenance nightmares and should be avoided when possible.
Quick Quiz: Strengthen Your Understanding of the Cascade
Question:
What color will the paragraph text render in the browser?
class="message">Hello, world!
And the CSS:
/* style.css (linked in the HTML head) */
.message {
color: green;
}
.message {
color: blue;
}
.message {
color: red !important;
}
Options:
- A) Green
- B) Blue
- C) Red
- D) Red with
!important
, so it overrides the others
Wrapping Up
That's the end of this Part Two article of the "Why Isn't Your CSS Working?" series.
Here, we've covered cascading in depth — exploring how browsers determine which styles to apply when rules conflict.
But the most important takeaway is how Cascading and Specificity work together as soulmates of CSS — one providing the rules, the other providing the weight.
In the previous article - Why Isn't Your CSS Working? Understanding Specificity, we mastered specificity. Now, with both pieces of the puzzle, you're equipped to solve almost any CSS styling mystery you encounter.
In the next part of this series, we will be looking at Common Pitfalls and Best Practices to help you avoid frustrating debugging sessions and write more maintainable CSS.
I hope this helped you in your web development journey.
If you have any confusion, corrections, or suggestions, feel free to drop a comment below!
Thanks for reading.
SOLUTION OF THE QUIZ
Answer:
➡️ D) Red with !important
, so it overrides the others
Explanation:
Even though all the selectors have the same specificity (just a class selector), the cascade takes into account source order and importance.
Here's how the rules stack up:
-
style.css
sets the color to green. - An internal
tag (which comes after the external CSS) sets it to blue.
- Another
tag later sets the color to red, but this time with
!important
.
Because !important
overrides all normal declarations—regardless of specificity or order—the text color ends up being red.