Course topics

By WebNest Studio Engineering Team

CSS Tutorial

Understanding the CSS Cascade

The "C" in CSS stands for Cascading, and it describes the algorithm the browser uses to decide which declaration wins when multiple rules target the same element and the same property. Without the cascade, a stylesheet with conflicting rules would be ambiguous — the cascade makes the outcome predictable.

The cascade resolves conflicts through a strict, ordered sequence: first by origin and importance, then by specificity (covered in the next topic), and finally by source order. Learning this order removes the guesswork from debugging "why isn't my style applying?" — usually the answer lives somewhere in this sequence.

Why it matters

Several rules often set the same property on the same element, and the cascade is the set of rules that decides which one wins. Until you understand it, CSS feels random: a change has no effect, and nobody knows why. Once you do, you can predict the result and stop reaching for !important.

Origin and Importance

CSS declarations come from different origins, and the cascade ranks them before it even looks at specificity.

  • User-agent styles — the browser's built-in default stylesheet (e.g. default margins on <body>, default list bullets).
  • Author styles — the CSS you write for your site; this is what developers work with day to day.
  • User styles — custom styles a site visitor applies (e.g. via browser extensions or accessibility settings).
  • !important declarations — override normal cascade ordering for that specific origin, and author !important rules beat normal author rules regardless of specificity elsewhere.

Source Order as a Tie-Breaker

When two rules have identical origin, importance, and specificity, the cascade falls back to source order: whichever rule appears later in the stylesheet (or later in the document, for multiple linked stylesheets) wins. This is why the order you write or link your CSS files matters — a later rule with equal specificity silently overrides an earlier one.

Inheritance vs. the Cascade

Inheritance is a separate but related mechanism: some properties (like color, font-family, and line-height) automatically pass from a parent element to its children if nothing else sets them. Properties like margin, padding, and border do not inherit by default. An inherited value has the lowest priority in the cascade, so any explicit rule — no matter how simple — will override an inherited one.

Examples

Source order deciding the outcome between equally specific rules

CSS
<!-- <p class="note">Read this carefully.</p> -->

.note {
  color: blue;
}

.note {
  color: green; /* same specificity, appears later -> wins */
}
Output
The paragraph text renders green, because the second .note rule has identical specificity to the first but appears later in the stylesheet.

An !important declaration overriding a more specific selector

CSS
#sidebar .widget p {
  color: black;
}

p {
  color: red !important; /* wins despite lower specificity, due to !important */
}
Output
All paragraph text renders red, including text inside #sidebar .widget, because !important outranks normal specificity comparisons within the author origin.

Common Mistakes

  • Reaching for !important to "fix" a styling conflict instead of understanding why the conflicting rule was winning in the first place, which creates a stack of increasingly hard-to-override overrides.
  • Assuming that a rule later in the file always wins, forgetting that specificity is checked before source order.
  • Expecting non-inherited properties like border or padding to pass down from a parent element automatically.
  • Linking two stylesheets in the wrong order and being confused when the "correct" rule gets silently overridden by an equally specific rule from the other file.

Exercise

Set the text colour once on main so that the heading and the paragraph both inherit navy. Then override the paragraph alone to grey with a later rule. Finally, make the button use the inherited colour too; form controls do not inherit text colour by default.

Expected result: a navy heading, a grey paragraph and navy button text.

CSS · starter code
/* The page contains: <main> with an <h1>, a <p> and a <button> */

/* TODO: navy text for everything inside main */

/* TODO: the paragraph is grey instead */

/* TODO: the button takes the colour of its parent */
Show hints
  • color is an inherited property, so setting it on main reaches its children.
  • The keyword inherit forces a property to take its parent's value: color: inherit.
Show solution
CSS · solution
/* The page contains: <main> with an <h1>, a <p> and a <button> */

main {
  color: navy;
}

p {
  color: gray;
}

button {
  color: inherit;
}

Quick quiz

1. Two rules with the same selector set different colours on the same element. Which wins?

  • A. The first one in the file
  • B. Neither
  • C. The shorter one
  • D. The one that appears later
Show answer

D. When origin, importance and specificity are equal, source order decides.

2. Which of these properties is inherited by child elements by default?

  • A. margin
  • B. border
  • C. color
  • D. padding
Show answer

C. Text properties such as color and font-family inherit. Box properties such as margin and border do not.

3. Why should !important be avoided in ordinary code?

  • A. It is not supported by browsers
  • B. It slows the page down
  • C. It only works on colours
  • D. It overrides normal cascade rules, so the only way to beat it is another !important
Show answer

D. It leads to an escalating series of overrides that is hard to maintain.

Interview questions

How does the cascade decide which declaration applies?

Show answer

It compares competing declarations in order. First by origin and importance: browser defaults, then user styles, then author styles, with !important reversing that order. Then by specificity of the selector. Then by source order, the later declaration winning. Cascade layers, declared with @layer, add a step between origin and specificity. If no declaration applies at all, the property is inherited or takes its initial value.

What is the difference between the cascade and inheritance?

Show answer

The cascade resolves a conflict between several declarations that target the same element. Inheritance is what happens when no declaration targets the element for a property: certain properties, mostly those to do with text, take the value computed for the parent. A declaration that targets the element directly always beats an inherited value, however low its specificity.

Key Points to Remember

  • The cascade resolves conflicts in this order: origin and importance, then specificity, then source order.
  • Author !important declarations override normal author-origin rules regardless of specificity.
  • When specificity and origin are tied, the declaration that appears later in the source wins.
  • Inheritance is separate from the cascade and only applies to certain properties; inherited values have the lowest cascade priority.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Shows a live preview of your HTML, CSS and JavaScript. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering