Why Your CSS Isn’t Listening (And How to Make It Obey)

by Mylene — 7 minutes

Who this is for
If you’ve ever tweaked a color, nudged a margin, or tried to “just make it bold” — and nothing changed — you’re not alone. CSS can seem unpredictable, but once you understand how it decides which styles to apply, it starts making a lot more sense.

We're going to look under the hood of CSS: how styles compete, how the cascade works, why some rules win and others get ignored — and how to fix it when your layout refuses to behave.


What Even Is CSS?

CSS (Cascading Style Sheets) is the language we use to tell HTML how it should look. Fonts, colors, layouts, spacing, hover effects – it’s all there.

But styling isn’t just about what you write – it’s about where and how you write it. That’s where things like cascade and specificity come in. And they’re the reason CSS sometimes feels like a wild animal: usually cute, occasionally bites.


What Is the Cascade, Really?

The word “cascade” comes from the image of a waterfall — something that flows downward, step by step. In CSS, the cascade is the process by which the browser decides which styles to apply when there are multiple conflicting rules. The idea is that styles “flow” from different sources — some from your base styles, others from components, and maybe even a few from inline declarations or browser defaults.

Just like water flows from the top of a hill to the ground, styles flow from general to specific. And when multiple styles touch the same element, CSS decides which one lands last — but with a few rules to keep it fair.

The browser follows this cascade process to resolve conflicts:

  1. Specificity – How precisely the selector targets the element
  2. Source – Inline styles > external styles > browser defaults
  3. Order – If two rules are equally specific, the one that appears later wins

So it’s not just “who’s last.” It’s more like a waterfall made of rules: the most specific, heaviest drop will push the others aside — and the lightest won’t even make it to the bottom.

The cascade lets you define broad rules at the top and override them as needed further down. It's not a flaw — it's what makes CSS flexible.

“Cascading” in CSS refers to the process of resolving conflicts between rules. Imagine styles as paint being layered on top of each other — the final color you see is the result of many overlapping strokes.

The browser uses a set of rules to decide which style sticks when multiple ones apply:

  1. Specificity – How narrowly the rule targets the element
  2. Source – Inline styles beat external styles, which beat browser defaults
  3. Order – If two rules are equally specific, the one that comes last wins

So it’s not just “last one wins.” It’s “most specific and best placed wins.”

The cascade isn’t a bug — it’s what allows you to set broad styles globally and refine them where needed. A simple .button {} rule can shape all your buttons, while .form .button.primary lets you make specific exceptions. Once you understand it, it becomes a feature — not a fight.


Specificity: CSS Has a Hidden Points System

CSS selectors are secretly scored. This score decides how "strong" a rule is. It looks like this: a-b-c, where:

  • a = number of ID selectors
  • b = number of class selectors, attributes, and pseudo-classes
  • c = number of element selectors and pseudo-elements

Quick note: pseudo-classes (like :hover, :focus) act like conditions — they apply when something happens. Pseudo-elements (like ::before, ::after) insert extra content, virtually.

Selector Specificity Score
* (wildcard) 0-0-0
div 0-0-1
.menu 0-1-0
#header 1-0-0
style="..." (inline) highest override

Think of specificity like a stack of weights: #id is heavy, .class is lighter, and div is almost floating. The heaviest rule wins.

And specificity adds up. Look at this:

```css /* 0-2-1: two classes, one element */ div.button.primary { background-color: green; }

/* 1-0-0: one ID */ #submit { background-color: red; } ```

The second rule wins. Even if the first one is later in the file. That’s the power of specificity.

Troubleshooting: Why Your CSS Isn’t Applying

You’ve written a rule. You’re sure it’s correct. And nothing changes. Sound familiar?

It’s usually because your rule is being outranked in the cascade. Either:

  • Another rule is more specific
  • You wrote your rule too early
  • There’s an inline style or !important getting in the way

Here’s a common trap:

```css .button { color: blue; }

#hero .button { color: red; } ```

You try to make it blue again? Won’t work unless your new rule is at least as specific — or comes later. Try .page .button, or re-order your CSS files.


Real-World Conflict Example

Let’s walk through a scenario. You’ve got two stylesheets:

```css /* base.css */ .button { background-color: blue; }

/* overrides.css */ .button { background-color: green; } ```

Since they have equal specificity, the later one wins → green button.

Now you add this:

#checkout.button {
  background-color: red;
}

Boom. Red wins. Why? Because the specificity score is now higher (1-1-0 vs 0-1-0).


Don’t vs Do: IDs vs Classes

Don’t:

#nav {
  font-size: 1.2rem;
}

Do:

.nav {
  font-size: 1.2rem;
}

Why? Because classes are easier to override, reuse, and combine. You’ll thank yourself later.

New to CSS? Start by styling with classes only. Skip IDs for now. You'll thank yourself later when you're debugging.


The Danger of !important

This is the panic button. When nothing else works, people reach for:

.button {
  color: red !important;
}

And suddenly, it works. But now you’ve overridden everything – including your future self.

The problem? You’ve broken the cascade. And now every change down the line also needs !important, or it won’t take effect. It’s a slippery slope.

When should you use it? Almost never. Maybe when overriding third-party libraries. Maybe in accessibility tools. But in your own code? There's almost always a better way.


Style Bleeding: When CSS Gets Everywhere

You styled one component. Suddenly, the same style appears in places you didn’t expect. Welcome to bleeding styles.

Here’s an example:

<!-- Card component -->
<div class="card">
  <h2>Title</h2>
  <p>This is some text.</p>
</div>

```css /* This applies to all paragraphs in cards */ .card p { font-size: 1rem; }

/* Later you add this */ p { font-size: 0.7rem; } ```

Now even your .card p looks smaller. Why? Because the global p rule overrides it due to source order. Bleeding like this can break your layout.

How to prevent this:

  • Scope styles better (.card p should come after)
  • Use stricter selectors
  • Modularize your CSS (BEM, CSS Modules, etc.)
  • Avoid styling bare elements globally unless you really mean it

A Visual Metaphor: CSS as Clothing

Think of CSS like dressing a mannequin. You have base clothes (like a shirt and pants), then accessories, then maybe a jacket.

  • Cascade = the order you put them on
  • Specificity = how tightly something sticks (a belt holds more than a scarf)
  • !important = stapling a hat to the head. Yes, it stays – but good luck swapping it later.

How to Keep CSS Manageable

  • Use classes for styling. Keep IDs for anchors or JS hooks.
  • Keep specificity low and predictable.
  • Avoid !important unless you're in a fire drill.
  • Use DevTools to trace applied and overridden styles.
  • Structure styles to follow your components, not your chaos.

Mini Quiz: Let’s See What You’ve Learned

What color will the link be?

```css .menu li a { color: green; }

#mainNav .menu a { color: red; } ```

Assuming both apply to the same link, which rule wins?

Answer: Red. The second selector has an ID → 1-1-1 vs 0-2-1.


Wrapping Up

CSS isn’t a monster. But it does demand precision.

Once you understand how the cascade, specificity, and source order interact, things get way easier. You’ll spend less time guessing and more time designing.

And best of all? You’ll probably never need !important again.

meerdivotion

Cases

Blogs

Event