DEV Community

JSDev Space
JSDev Space

Posted on

Understanding CSS Priority — The Cascade Explained

Mastering the Priority of CSS Styles

CSS Cascading and Specificity are the foundation of how browsers decide which styles to apply. In this article, we’ll explore how multiple CSS rules interact and which one takes precedence — from classic specificity formulas to modern @layer rules.


🤔 Let’s Start with a Simple Example

When multiple CSS classes are applied to one element:

<div class="blue red green">What color is this text?</div>
Enter fullscreen mode Exit fullscreen mode
.blue { color: blue; }
.red { color: red; }
.green { color: green; }
Enter fullscreen mode Exit fullscreen mode

The final color is green.

This happens because CSS follows a cascading order, where later declarations take precedence when all else is equal.


🕰️ The Birth of Cascading

When CSS was first introduced in 1996, cascading was its key concept.

The design goals were:

  • 🎯 Predictability: Developers can reason about the final result.
  • ⚙️ Flexibility: Allow style overrides and inheritance.
  • ⚖️ Balance: Respect both author and user styles.

This concept, created by Håkon Wium Lie, was meant to handle conflicts between multiple sources — author styles, user styles, and browser defaults.


⚖️ The System of Cascading Priorities

🎯 Specificity Formula

Specificity is represented as a four-part tuple:

(Inline, ID selectors, Class/Attribute/Pseudo-class, Element selectors)
Enter fullscreen mode Exit fullscreen mode
Style Type Weight Example
Inline style 1000 style="color: red"
ID selector 100 #header
Class/attribute/pseudo-class 10 .active, [type=text]
Element selector 1 div, p
Universal selector 0 *

🔍 Real Examples

/* Specificity: (0, 0, 1, 1) = 11 */
div.blue { color: blue; }

/* Specificity: (0, 1, 0, 0) = 100 */
#content { color: red; }

/* Specificity: (0, 0, 2, 1) = 21 */
div.blue.active { color: green; }

/* Inline style: (1, 0, 0, 0) = 1000 */
<div style="color: yellow;">
Enter fullscreen mode Exit fullscreen mode

⚠️ Note: Ten class selectors will never outweigh a single ID selector.


📝 Overriding Rules at Equal Priority

When selectors share the same specificity, source order decides which one wins.

.blue { color: blue; }
.red { color: red; }
.green { color: green; }
Enter fullscreen mode Exit fullscreen mode

HTML order doesn’t matter — only the CSS definition order does:

<div class="green blue red">Green</div>
<div class="red green blue">Green</div>
<div class="blue red green">Green</div>
Enter fullscreen mode Exit fullscreen mode

🎨 Priority in Complex Scenarios

<!DOCTYPE html>
<html>
<head>
<style>
  div.red { color: red; }           /* 11 */
  .blue.text { color: blue; }       /* 20 */
  #content { color: green; }        /* 100 */
  .yellow { color: yellow; }        /* 10 (later defined) */
</style>
</head>
<body>
  <div id="content" class="red blue text yellow">
    What color is this?
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

✅ Result: Green — because the ID selector has the highest priority.

If the ID is removed, blue.text (20) wins over red (11).


⚡ The Power of !important

.blue { color: blue !important; }
.red { color: red; }
.green { color: green; }
Enter fullscreen mode Exit fullscreen mode

!important overrides all other declarations, even with lower specificity.

💡 Usage Tips

✅ Use for overriding library defaults or utility classes.

❌ Avoid in component-level styles — it leads to “priority wars.”


🛠️ Best Practices in CSS Architecture

A recommended CSS priority structure:

/* 1. Reset styles — lowest priority */
* { margin: 0; padding: 0; }

/* 2. Base elements */
h1, h2, h3 { font-family: Arial, sans-serif; }

/* 3. Layout classes */
.container { max-width: 1200px; }

/* 4. Components */
.button { padding: 8px 16px; }

/* 5. States */
.button.active { background: blue; }

/* 6. Utilities — highest */
.text-center { text-align: center !important; }
Enter fullscreen mode Exit fullscreen mode

🎯 Avoiding Conflicts

  1. Use BEM naming:
   .card__title--highlighted { color: red; }
Enter fullscreen mode Exit fullscreen mode

Instead of deeply nested selectors:

   .card .content .title.highlighted { color: red; }
Enter fullscreen mode Exit fullscreen mode
  1. Modular CSS-in-JS:
   const styles = {
     title: { color: "red" },
     subtitle: { color: "blue" },
   };
Enter fullscreen mode Exit fullscreen mode
  1. Custom properties for flexibility:
   .theme-blue { --primary-color: blue; }
   .button { color: var(--primary-color, gray); }
Enter fullscreen mode Exit fullscreen mode

🆕 Modern CSS: Cascade Layers

CSS now includes the powerful @layer feature:

@layer base, components, utilities;

@layer base {
  h1 { color: black; }
}

@layer components {
  .title { color: blue; }
}

@layer utilities {
  .text-red { color: red; }
}
Enter fullscreen mode Exit fullscreen mode

Cascade order: base < components < utilities

This gives fine-grained control and clarity for large projects.


🔮 Logical Properties and Modern Trends

As CSS evolves with globalization and layout flexibility, logical properties change how cascading behaves:

.text {
  margin-inline-start: 20px;
  margin-left: 10px;
}
Enter fullscreen mode Exit fullscreen mode

In browsers supporting logical properties, margin-inline-start takes precedence over margin-left.


📚 References

Top comments (0)