Suggest an editImprove this articleRefine the answer for “What is cascade in CSS”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Cascade in CSS** is the algorithm that picks the winning style value per property when multiple rules match the same element. Sort order: Origin > Importance > Specificity > Source order. A class selector beats a tag selector, `!important` beats inline styles, and a later rule wins only when specificity ties. **Key point:** cascade merges per property, not per rule.Shown above the full answer for quick recall.Answer (EN)Image**Cascade in CSS** is the algorithm browsers use to resolve conflicts by selecting the winning style value for each property when multiple CSS rules target the same element. ## Theory ### TL;DR - Cascade picks **one value per property** from all matching rules, not one winning rule overall. - Sort order: Origin > Importance > Specificity > Source order. - `!important` flips priority within each origin tier, it does not skip specificity entirely. - A later rule wins only when specificity is equal. - A rule can lose `color` and still contribute `font-size` to the same element. ### Quick example ```html <style> p { color: blue; } /* loses: lower specificity */ .highlight { color: red; } /* wins: class beats tag selector */ </style> <p class="highlight">This text is red.</p> <!-- red --> <p>This text is blue.</p> <!-- blue --> ``` Both rules match the first `<p>`. Cascade picks `.highlight` for `color` because a class selector (specificity 0,0,1,0) beats a tag selector (0,0,0,1). No conflict on any other property, so nothing else changes. ### How cascade resolves conflicts Browsers sort all matching declarations in this exact order: 1. **Origin and importance.** User-agent styles (browser defaults) sit at the bottom. Your author styles come next. User styles from browser extensions or OS settings sit above those. Adding `!important` flips each tier: author `!important` beats normal author, user `!important` beats almost everything. 2. **Specificity.** Scored as a four-part tuple: inline styles (1,0,0,0), IDs (0,1,0,0), classes and attributes and pseudo-classes (0,0,1,0), tags and pseudo-elements (0,0,0,1). Compare left to right. `#header a` (0,1,0,1) beats `.menu a` (0,0,1,1) because the ID column wins immediately. 3. **Source order.** If everything else ties, the declaration that appears last in the document wins. ### Key difference from what most people assume Cascade does not apply one winning rule and discard the rest. It picks the winning value **per property**. A rule with `color: red; font-size: 16px` can lose `color` to another rule and still contribute `font-size` to the computed style. That merge step is where most people get confused, because they expect one rule to take over completely. ### When to use each approach - **Simple site, no conflicts** - keep specificity low and rely on source order. - **Component library conflicts** - boost specificity with BEM-style selectors like `.card__button--primary` before reaching for `!important`. - **Fighting third-party CSS** - use `!important` as a last resort, not a first move. Inline styles are a better short-term option. - **Theming system** - layer your stylesheets: base, then theme, then user preferences. CSS `@layer` (supported in all major browsers since 2022) makes this explicit. - **Debugging mystery styles** - open DevTools "Styles" pane. It shows every matching declaration, which one won, and why the rest are crossed out. ### How the browser handles this internally Chrome's Blink engine parses all stylesheets into a cascade tree sorted by origin. During layout, it matches selectors for each element, scores specificity, and walks the tree. Highest origin/importance/specificity/order wins per property. Values that do not conflict merge into the computed style object. That last part, the merge, is the bit the cascade spec describes but most tutorials skip entirely. ### Common mistakes - **Assuming later rules always win** ```css p { color: red; } /* first in code, but wins anyway */ div p { color: blue; } /* later in code, but loses */ ``` `div p` has specificity 0,0,0,2 and `p` has 0,0,0,1. Specificity beats source order. - **Using `!important` as a quick fix** I've watched teams go through `!important` wars that lasted weeks because one developer used it in a shared component and nobody could override it cleanly. ```css .btn { color: black !important; } /* theme overrides now broken */ ``` Fix: raise specificity instead. `.theme-dark .btn { color: white; }` works without poisoning everything downstream. - **Thinking inline styles always win** ```html <p style="color: blue" class="override">Text</p> <style>.override { color: red !important; }</style> <!-- Output: red --> ``` `!important` beats inline styles. Only adding `!important` to the inline value itself would flip it back. - **Ignoring user stylesheets** Browser extensions inject CSS at the user-origin tier, which overrides your author styles without any warning. If something looks broken in a user's browser but not yours, check for extension interference. DevTools lets you emulate user stylesheets to test this. ### Real-world usage - **Tailwind CSS** - utility classes like `bg-red-500` win over base CSS via specificity or source order. Non-conflicting properties from your base still apply. - **Bootstrap** - `.btn-primary` (class plus tag specificity) overrides a generic `.btn` rule. - **Styled Components / Emotion** - generates scoped class names, but cascade still applies across libraries loaded on the same page. - **Material UI** - CSS custom properties combined with cascade handle theme overrides at the property level. ### Follow-up questions **Q:** What is the full cascade sort order? **A:** Origin and importance first (user-agent < user < author, `!important` flips within each tier), then specificity (inline > ID > class/attr/pseudo-class > tag), then source order. **Q:** How does specificity calculate? **A:** It is a four-part tuple (A, B, C, D): A equals 1 for inline styles, B counts IDs, C counts classes and attributes and pseudo-classes, D counts tags and pseudo-elements. Compare left to right. Combinators like `>` and `+` add nothing to the score. **Q:** What happens when specificity is equal? **A:** The last declaration in document order wins for normal rules. For `!important` declarations it reverses: the first one wins. **Q:** Does cascade work the same inside Shadow DOM? **A:** No. Shadow DOM encapsulates its own cascade. Constructable stylesheets (adopted sheets, Chrome 101+) merge into the shadow cascade without touching the light DOM. Inline styles on the host element still beat shadow `!important` declarations, which trips up Web Component developers who expect encapsulation to be total. **Q:** How do CSS Custom Properties interact with cascade? **A:** Custom properties cascade just like any other declaration. `--color: red` wins based on normal cascade rules. The substitution `color: var(--color)` happens after cascade resolves the variable's winning value, not before. ## Examples ### Specificity conflict with merged properties ```html <!DOCTYPE html> <html> <head> <style> p { color: blue; font-size: 14px; } /* tag selector, specificity 0,0,0,1 */ .highlight { color: red; } /* class selector, specificity 0,0,1,0 */ </style> </head> <body> <!-- color: red from .highlight, font-size: 14px from p (no conflict there) --> <p class="highlight">Red text, 14px font.</p> </body> </html> ``` `.highlight` wins `color`. But `font-size` from `p` still applies because nothing else declares it. Both rules contribute to the final computed style. That is the merge in action. ### Cascade in a React and Tailwind setup ```jsx /* App.css */ .button { background: gray; padding: 8px; border-radius: 4px; } /* Tailwind generates: */ /* .bg-blue-500 { background-color: rgb(59 130 246); } */ function Button({ primary }) { return ( <button className={`button ${primary ? 'bg-blue-500' : 'bg-gray-500'}`}> Click me </button> ); } /* Result for a primary button: background: rgb(59 130 246) from Tailwind (same specificity, loads later, wins) padding: 8px from .button (no conflict, merges in) border-radius: 4px from .button (no conflict, merges in) */ ``` Both `.button` and `.bg-blue-500` are class selectors with equal specificity. Tailwind wins `background` by source order because its generated stylesheet loads after yours. The padding and border-radius from `.button` merge in because Tailwind never declares them. This is the standard Tailwind pattern in Next.js apps.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.