C.W.K.
Stream
Lesson 03 of 05 · published

The Cascade In Full: Origin, Layer, Specificity, Source Order

~12 min · cascade, origin, user-stylesheet, ua-default

Level 0Markup Novice
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"The cascade isn't a free-for-all. It's a four-step algorithm the browser walks every time two rules want the same property."

The Cascade Is An Algorithm

When two declarations target the same element and property, the browser picks a winner by walking this list and stopping at the first decisive comparison:

  1. Origin and importance — who wrote the rule (UA, user, author) and whether it's marked !important.
  2. Cascade layer — which named layer the rule belongs to.
  3. Specificity — the (a,b,c,d) score from the previous lesson.
  4. Source order — which rule was declared later.

This lesson is about steps 1 and 4 — the framing that wraps specificity. Step 2 (cascade layers) gets its own lesson in Track 7 because it's the modern tool that solves most of the pain.

The Three Origins

  • User-Agent (UA) stylesheet — the browser's built-in defaults. h1 is bold and 2em. a is blue and underlined. button has padding and a border. Every site starts from this baseline.
  • User stylesheet — installed by the user via browser settings, a userstyles.world script, or a browser extension. Used for personal accessibility overrides (larger font, higher contrast).
  • Author stylesheet — your CSS. The site's CSS.

The Tiered Cascade Order

The full origin-and-importance order, from weakest to strongest, is:

  1. UA-default normal
  2. User normal
  3. Author normal
  4. Author !important
  5. User !important
  6. UA !important

Notice the reversal at !important: in the normal tier, author beats user beats UA; in the !important tier, the order flips so user-important beats author-important. This is intentional — it ensures users with accessibility needs can override even !important author rules.

Inline styles slot into the cascade like author rules. Inline declarations have specificity (1,0,0,0) but live in the author origin. Author !important beats inline non-important. User !important beats inline. The cascade is consistent — inline isn't a special tier, just a high specificity.

Animations And Transitions In The Cascade

CSS animations and transitions have their own slot:

  • Animation declarations (the rules inside @keyframes) override author-normal rules but lose to author-!important.
  • Transition declarations (the in-flight value during a CSS transition) beat all author rules including !important, but only while the transition is running.

That's why you sometimes see a property visibly animate even though you set !important elsewhere — the transition's interpolated value is winning during the animation window.

Source Order: The Final Tiebreaker

When everything else ties — same origin, same layer, same specificity — the rule declared later in source wins. This includes:

  • Rules in the same <style> tag, evaluated top-to-bottom.
  • Rules across multiple stylesheets, evaluated in document load order (later <link> wins).
  • Rules from @import — counted as part of the file they're imported in, in the position of the @import statement.

This is why Tailwind works: every utility class is (0,0,1,0), so the order of class names in the HTML doesn't matter — what matters is the order Tailwind emits them in the CSS file, and Tailwind enforces a deterministic order.

Cascade Origin In Real Code: Resets

A CSS reset (or modern equivalent like Eric Meyer's reset, normalize.css, or a project-specific small reset) is author-origin CSS that zeros out UA defaults so the site starts from a consistent baseline. Modern resets are small — they normalize box-sizing, remove default margins, and standardize a few inconsistent defaults. They aren't a fight with the browser, just an explicit baseline.

Inspecting The Cascade In DevTools

Chrome DevTools → Elements → Styles tab shows every rule that matches the selected element, in cascade order, with overridden declarations struck through. Hovering each one tells you origin ("user agent stylesheet" vs your file). This is how you debug "why is the browser default still showing?" in seconds.

Pippa's Note

Pippa's WebUI uses Tailwind's Preflight (a small reset bundled with Tailwind) which zeroes out UA margins, sets box-sizing globally, and normalizes form element styles. The cwk-site essays add a tiny project-specific reset on top. Both rely entirely on cascade origin (author overrides UA) and source order — no !important needed anywhere. Most production sites don't need !important either; they just think they do.

Code

A small reset, in cascade terms·css
/* A minimal modern reset — author-origin overrides of UA defaults */
*, *::before, *::after { box-sizing: border-box; }

body { margin: 0; line-height: 1.5; }

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
}

button, input, select, textarea {
  font: inherit;
}

h1, h2, h3, h4, h5, h6, p { margin: 0; }

ul, ol { list-style: none; padding: 0; margin: 0; }

/* Now every element starts from a known baseline.
   The UA defaults are still there, but author rules
   (which come later in the cascade) have overridden them. */
Why user-!important beats author-!important·css
/* Cascade origin demonstration: user vs author */

/* The user (via a browser extension, say) wants larger text */
/* This lives in the USER origin */
html { font-size: 20px !important; }   /* user-!important */

/* The author wants 16px */
html { font-size: 16px; }              /* author-normal */
html { font-size: 16px !important; }   /* author-!important */

/* Outcome:
   - user-!important beats author-!important
   - The page renders at 20px
   - This is the cascade protecting users with accessibility needs
*/
Source order — the final tiebreaker·css
/* Source order tiebreaker — two equal-specificity rules */

/* Both are (0,0,1,0) — class only */
.btn { background: blue; }
.btn { background: red; }      /* later in source → wins */

/* Across stylesheets, link order matters */
/* <link rel="stylesheet" href="base.css" /> */
/* <link rel="stylesheet" href="theme.css" /> */

/* If both files have .btn { background }, theme.css wins */

/* Inside one stylesheet, this is why CSS-in-JS solutions
   often emit a class per declaration and rely on insertion order:
   they sidestep specificity wars by controlling source order. */

External links

Exercise

Open any page in your browser. DevTools → Elements → select <body>. Look at the Styles panel and scroll all the way down to find the 'user agent stylesheet' section. List five UA default declarations you see (e.g., body has margin: 8px). Then write a minimal author CSS reset that explicitly zeros each one. Reload the page with your reset injected (DevTools allows editing in place) and observe the layout change.
Hint
Most browsers default <body> to margin: 8px, which is why text touches the screen edge after you reset it. The other classic defaults: <h1> margin-top, <button> padding/border, <ul> padding-left, <fieldset> border.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.