CSS Cascade and Specificity Rule¶
Resolution rule — instantiates Controlled Inheritance Propagation
Resolves which declaration wins when several target the same property, ranking them by origin, importance, specificity, and source order so conflicts settle deterministically.
CSS Cascade and Specificity Rule is the conflict-resolution engine of inheritance. Where a fall-through tree assumes one owner per value, real declarative systems let many rules target the same property at once — a global stylesheet, a component's own styles, a utility class, an inline attribute — and something must pick a winner deterministically. The cascade does it not by position in a lineage but by weight: it ranks every applicable declaration by origin (user-agent vs author vs user), importance (!important), selector specificity, and finally source order, and the top-ranked declaration wins. Its defining idea is that overrides compete by the declared specificity of their scope — a more precise selector beats a broader one no matter where it sits — so an override is a design lever you aim, not an accident of ordering.
Example¶
A team ships a design system in which button { background: blue } is the default. One marketing page needs a single green call-to-action. Rather than edit the shared rule (which would recolor every button in the product), they write a more specific selector — .cta.cta--promo { background: green } — and the cascade resolves the clash: a two-class selector out-specifies a bare element selector, so the promo button turns green while every other button stays blue.
Later a contractor drops style="background:red" directly on that button; inline styles outrank any selector, so red wins — until the design-system rule adds !important, which the team reserves for a small set of brand-locked properties precisely so they can win the cascade on purpose. The entire negotiation happens by weight, with no edit to the base rule and every competing declaration still visible in tooling.
How it works¶
- Gather every declaration that applies to the element and property, from all origins.
- Rank them in cascade order: origin and importance first, then specificity (an ID beats a class beats an element), then source order as the final tiebreak.
- Compute the winner as the value; the losers are overridden but remain inspectable.
- Decide inheritance separately — some properties (color, font) pass to descendants by default, others (margin, border) reset; the
inherit/initial/unsetkeywords let a rule opt in or out.
Its distinguishing move is that overrides are ranked by how specifically they were scoped: you win a conflict by being more precise about what you target, which makes precedence a deliberate, inspectable function rather than a matter of proximity.
Tuning parameters¶
- Specificity budget — how much selector weight your conventions permit. Flat, low-specificity systems stay easy to override; deep ID-laden ones become impossible to beat without escalation.
!importantreservation — whether importance is banned, free, or reserved for a named set (brand locks, resets). Reserving it keeps it a deliberate invariant instead of an escalation weapon.- Explicit layers — modern
@layerdeclares precedence bands directly, so a low-layer rule loses to a high-layer one regardless of specificity — trading implicit specificity math for stated ordering. - Inherited-property set — which properties propagate to descendants by default; widening it spreads values freely, narrowing it forces explicit setting.
- Source-order reliance — how much you lean on "last rule wins" as the tiebreak; heavy reliance makes the result sensitive to bundler and import ordering.
When it helps, and when it misleads¶
Its strength is surgical override without touching the base: the more precisely you scope an exception, the more locally it applies, and the winner of any clash is a deterministic function of rules you can read. That is what lets a shared stylesheet and a one-off page coexist.
Its signature failure mode is the specificity war. Because a more specific selector always wins, teams escalate — one deep selector begets a deeper one, and !important begets !important, until overriding anything means out-specifying a tower of accidental precedent. At that point the source no longer tells you what an element looks like; only the computed result does. The classic misuse is reaching for !important to win right now, which inverts the cascade and forces everyone downstream to escalate in turn.[1] The discipline is to keep specificity flat and uniform, reserve !important for declared invariants, and use explicit layers so precedence is stated rather than accumulated.
How it implements the components¶
CSS Cascade realizes the conflict-resolution side of the archetype — deciding which of several competing declarations governs:
precedence_and_conflict_rule— the cascade order (origin, importance, specificity, source order) is the rule that settles every clash deterministically.override_scope_declaration— a selector declares exactly what an override targets and how narrowly; specificity is that scope made quantitative.invariant_vs_default_boundary—!important, together with the default-inherit vs default-reset split, marks which declarations are hard to override versus freely overridable defaults.
It does NOT model the lineage or the catalog of what may be set — that substrate is Configuration Inheritance Tree and Object-Oriented Class Inheritance; nor does it trace a change's downstream blast radius — that's Lineage Impact Analysis Report.
Related¶
- Instantiates: Controlled Inheritance Propagation — the precedence engine that lets a scoped override win a conflict without editing any ancestor.
- Sibling mechanisms: Configuration Inheritance Tree · Object-Oriented Class Inheritance · Effective Configuration Diff · Inheritance Lint or Static Analysis · Lineage Impact Analysis Report · Override Expiry Workflow · Permission Inheritance with Explicit Denial · Policy Inheritance Matrix · Prototype Delegation Chain · Trait or Mixin Composition Rule · Platform Variant Option Model · Schema Extension and Override Check · Template Clause Override Register
References¶
[1] Specificity and the cascade order are defined by the W3C CSS Cascading and Inheritance specification, where !important is intended as a deliberate, sparing escape hatch. The widely-observed "specificity war" is what follows when it is used routinely instead — each escalation raising the bar every later override must clear. ↩