Cascade, Inheritance, and Specificity

Introduction

Most CSS confusion comes from one question: why did this rule win? The answer is usually the cascade, inheritance, and specificity working together. This chapter gives you a practical model for resolving style conflicts without random trial-and-error edits.

Prerequisites

  • Basic CSS syntax and selectors
  • Familiarity with class and ID selectors
  • A browser with DevTools

The Cascade: How CSS Chooses a Winner

When multiple declarations target the same property on the same element, CSS resolves conflicts using the cascade.

At a practical level, think in this order:

  1. Importance (!important)
  2. Specificity
  3. Source order (later rules win when specificity ties)

Example:

css
.title {
  color: #334155;
}
 
.title {
  color: #2563eb;
}

The second rule wins because it appears later.

Inheritance: Styles Passed from Parent to Child

Some properties naturally inherit from parent elements, so children receive values automatically.

Common inherited properties:

  • color
  • font-family
  • font-size (unless overridden)
  • line-height

Example:

css
body {
  color: #1e293b;
  font-family: system-ui, sans-serif;
}

Most text elements inside body inherit these values.

Common non-inherited properties:

  • margin
  • padding
  • border
  • width / height
  • background

If a property does not inherit, you must apply it directly where needed.

Specificity: Selector Strength

Specificity decides which selector is stronger when multiple rules target the same property.

Rough strength ranking:

  • Inline style (strong)
  • ID selector (#id)
  • Class / attribute / pseudo-class (.class, [type="text"], :hover)
  • Element / pseudo-element (h1, ::before)

Simple examples:

css
p {
  color: #0f172a;
}
 
.note {
  color: #2563eb;
}

For <p class="note">, .note wins because class specificity is higher than element specificity.

Specificity in Action

HTML:

html
<p id="intro" class="note">Welcome</p>

CSS:

css
p {
  color: #0f172a;
}
 
.note {
  color: #2563eb;
}
 
#intro {
  color: #dc2626;
}

#intro wins because ID specificity is higher.

Source Order Still Matters

If specificity is equal, later declaration wins:

css
.button {
  background: #2563eb;
}
 
.button {
  background: #1d4ed8;
}

Second rule wins due to source order.

This is why stylesheet import order and rule placement matter in larger projects.

What !important Does

!important is a CSS force flag for priority. Its job is to push one declaration to the highest importance level. Normally, CSS decides winners with specificity and source order; once a declaration has !important, it usually beats conflicting normal rules (rules without !important).

What the Syntax Looks Like

The format is:

text
property: value !important;

Note: !important comes after the value, and the semicolon still goes at the end.

css
.button {
  background: #2563eb !important;
}

This means: keep .button’s background as #2563eb when possible—even a later, higher-specificity normal rule often cannot override it.

A Side-by-Side Example

Without !important, the ID selector wins:

html
<button id="submit" class="button">Submit</button>
css
.button {
  background: #2563eb;
}
 
#submit {
  background: #dc2626;
}

Result: the button background is red, because #submit has higher specificity than .button.

If you add !important to the class rule:

css
.button {
  background: #2563eb !important;
}
 
#submit {
  background: #dc2626;
}

Result: the button background is blue. .button has lower specificity, but with !important it beats the normal #submit rule.

Use Cases and Risks

Use cases:

  • utility override layers
  • controlled exceptions in design systems

Risks:

  • hard-to-override rules
  • cascading “importance wars”
  • reduced maintainability

Warning

Use !important Sparingly

If you frequently need !important, the real issue is usually selector architecture or file order.

Practical Conflict Debugging

When a style does not apply:

  1. Inspect element in DevTools
  2. Check if selector matches
  3. Find crossed-out declaration
  4. Compare winning rule specificity
  5. Check load order and file order
  6. Verify inherited vs non-inherited property behavior

This method solves most “CSS not working” cases quickly.

Resetting and Explicit Keywords

Useful keywords when dealing with cascade and inheritance:

  • inherit: force element to inherit parent value
  • initial: reset to CSS initial value
  • unset: acts like inherit for inherited properties, initial for others
  • revert: reverts to earlier cascade origin

Example:

css
.card a {
  color: inherit;
}

This makes links inside .card use the card text color unless overridden.

Architecture Tips to Avoid Specificity Problems

  • Prefer class selectors over IDs for styling
  • Keep selectors shallow
  • Organize styles in predictable layers (base, components, utilities)
  • Avoid over-nesting in preprocessors
  • Use naming conventions consistently

Good architecture reduces conflict before debugging is needed.

Tip

Winning by Design

The best CSS strategy is not “stronger selectors,” but clearer structure and predictable layering.

Mini Exercise

Create this HTML:

html
<article class="post">
  <h2 id="post-title" class="title">Cascade Demo</h2>
  <p class="text">Learning specificity.</p>
</article>

Then:

  1. Add conflicting color rules for h2, .title, and #post-title
  2. Predict winner before checking browser
  3. Reorder rules and observe source-order changes
  4. Add one !important and observe impact
  5. Remove !important and solve using better selector strategy

FAQ

Which is more important: specificity or source order?

Specificity first. Source order decides only when specificity ties.

Why does text color inherit but margin does not?

Because inheritance is property-specific by CSS design. Text-related properties often inherit; box-model properties usually do not.

Is using IDs for styling always wrong?

Not always, but heavy ID-based styling increases specificity pressure and makes overrides harder in larger codebases.

Should I ban !important completely?

You can allow it in limited, intentional cases, but it should be rare and justified.

How do I get better at specificity debugging?

Use DevTools daily and always ask: selector match, specificity strength, and source order. With repetition, conflict resolution becomes fast.