CSS Cascade Origin Levels

CSS cascade origin order — UA, user, author, animation, !important — with layer position.

Reference for the CSS cascade algorithm origin and layer precedence, from user-agent and user styles through author styles, cascade layers, animations and the !important reversal, ranked highest to lowest priority. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Does the cascade run before or after specificity?

Origin and importance are checked first. Only when two declarations share the same origin and importance does the cascade fall through to cascade layers, then specificity, then source order. So a high-specificity author rule still loses to a user-agent !important rule.

What the cascade decides

When several CSS declarations set the same property on the same element, the cascade picks the winner. Before specificity or source order ever come into play, the cascade first sorts declarations by their origin (who wrote them) and importance (normal vs !important). Getting this order right explains why a heavily-specific author rule can still lose to a humble user-agent default marked !important.

How it works

The cascade compares declarations top to bottom through these tiers (highest priority first):

  1. Transitions
  2. User-agent !important
  3. User !important
  4. Author !important
  5. CSS animations
  6. Author normal
  7. User normal
  8. User-agent normal

The key insight is the !important reversal: for normal declarations the order is author over user over user-agent, but for !important declarations it flips to user-agent over user over author. This protects user and accessibility overrides. Cascade layers (@layer) subdivide the author tiers, and only when two declarations tie on all of the above does the engine fall through to specificity and then source order.

Why !important reverses the order — the accessibility rationale

The reversal exists because CSS was designed to balance the interests of page authors and end users. In normal declarations, authors take priority: they know their design. But an accessibility user who has configured their browser to display large text, high-contrast colours, or a specific font must be able to override the author unconditionally. Marking their stylesheet rules !important pushes them above the author, and the user-agent’s own !important rules (for browser UI consistency) sit above even that.

Where cascade layers fit

@layer subdivides the author normal and author !important tiers only. It does not interact with user or user-agent styles. Within author normal, the declared layer order wins: rules in a later-declared layer beat those in an earlier one, regardless of specificity. Unlayered author styles are treated as belonging to an implicit top layer that beats all explicitly named layers.

Under !important, the layer order reverses — the same mirror that applies at the origin level. A rule in the earliest-declared layer gets the highest !important priority, which means framework resets marked !important can be safely overridden by user code even in the important tier.

Debugging a rule that “won’t apply”

If a style is not applying despite an apparently winning selector, work through this checklist in order:

  1. Is a transition or animation currently running on the property? Transitions sit at tier 1 and will visually override everything during their duration.
  2. Is a browser user-stylesheet or accessibility extension adding a !important rule? Those sit at tiers 2 and 3.
  3. Did you mark something !important in your own stylesheet that is now blocking the new rule?
  4. Only after clearing these should you investigate specificity and source order.

Tips and notes

A transition always wins so animation never jams behind a static !important rule. Within author styles, unlayered declarations beat layered ones for normal rules — but that too reverses under !important. If a rule “won’t apply” despite high specificity, check whether something higher in this origin table (often a user-agent or user !important) is quietly outranking it. The comparison tool below resolves any two declarations for you.