FreeToGenerate.com

Resolves competing CSS the way the cascade does, and names the step that decided it — because specificity is the fifth of six, not the first. Nothing is uploaded.

Layer statements, layer blocks and ordinary rules. Every declaration found is entered into the cascade below, so keep it to the rules that are actually competing.

Try one:

Which declaration wins

Winner
audio { display: flex}
Decided at
Cascade layers — step 4

Layer order

  1. 1reset
  2. 2unlayered — the implicit final layer

Layers are sorted by the order they first appear, whether that is in a statement or a block. Later beats earlier for normal declarations.

Every declaration, strongest first

#SelectorLayerImportanceSpecificity
1audiounlayerednormal0-0-1
2audio[controls]resetnormal0-1-1
  • An unlayered declaration is competing against layered ones, and it wins the layer step regardless of specificity. Anything not assigned to a layer joins an implicit final layer, and for normal declarations the last layer takes precedence.

The full sorting order

#StepApplied here
1Origin and importance — step 1Yes
2Context — step 2No — needs a live document
3Element-attached styles — step 3Yes
4Cascade layers — step 4Yes
5Specificity — step 5Yes
6Order of appearance — step 6Yes

The cascade works down this list and stops at the first step that separates two declarations. Specificity is the fifth of six, which is why it so often decides nothing.

Everything here runs in your browser. No CSS is uploaded.

Also available in: Español · Português · Français · العربية

CSS cascade layers: which rule wins, and at which step

Paste competing CSS and see which declaration the cascade picks — and which of its six steps decided it, which is almost never specificity.

What cascade layers are

A cascade layer is a named bucket you put CSS into so that whole groups of rules can be ordered against each other, without touching a single selector. You declare the order once — @layer reset, components, utilities — and from then on anything in utilities beats anything in components, regardless of how the selectors compare. It is the mechanism CSS gained for the problem that specificity was never designed to solve: keeping a framework, a component library and your own overrides from fighting.

The rule that surprises everyone is what happens to CSS that is not in a layer. The specification says any declaration not assigned to an explicit layer is added to an implicit final layer — and since later layers beat earlier ones, unlayered styles beat every layer you declared. Not because they are more specific, and not because they come later in the file. Because being unlayered puts them last in the layer order.

The specification demonstrates this itself. It shows a bare audio rule with a specificity of 0,0,1, written first, beating an audio[controls] rule of 0,1,1 inside a reset layer — and says outright that the unlayered declarations take precedence even though they have lower specificity and come first in the order of appearance. That is the default example on this page, and the tool reports the layer step as the one that decided it.

How to use it

  1. Paste the rules that are competing. Layer statements, layer blocks and ordinary rules are all read. Keep it to the declarations actually in contention — the cascade resolves one property at a time, and the tool says so if it finds more than one.
  2. Read the deciding step, not just the winner. The verdict names which of the six steps separated the top two. That is the part worth knowing: if it says step four, no amount of adding classes to a selector will change the outcome.
  3. Check the layer order. It is listed in the order the browser uses, with the implicit final layer for unlayered styles shown at the bottom where it actually sits. The sample buttons cover the specification's own example, an !important that backfires, a layer order set upfront, and a contest that does fall through to specificity.

Why !important makes an unlayered rule weaker

This is the part that reads like a bug and is not. The specification says that when comparing declarations in different layers, for normal rules the declaration in the latest layer wins — and for important rules the declaration in the earliest layer wins. Importance reverses the layer order completely.

Now combine that with the implicit final layer. An unlayered declaration sits last, which makes it the strongest among normal declarations. Mark it !important and the ordering flips: last is now weakest, so the same rule goes from beating every layer to losing to all of them. Adding !important to an unlayered override, which is the reflex when something will not apply, is precisely the wrong move — it is the second sample button on this page.

The specification's note explains why this is consistent rather than perverse: it follows the same logic as the origin order, where important author styles are weaker than important user styles even though normal author styles are stronger than normal user ones. The !important flag exists so the party lower down the stack can enforce something the party above cannot override. Layers inherit that logic, so the flag means give way to the base layer, not win at all costs.

The practical consequence is worth stating plainly. If you are using layers and you need an override to win, put it in a later layer rather than reaching for !important. And if you already have !important scattered through unlayered CSS, adopting layers will change which of those rules win, in a direction that is not obvious from reading them.

Specificity is the fifth step of six

The cascade sorts declarations by six criteria in order, and stops at the first one that separates them. Origin and importance come first, then context, then whether the declaration is attached directly to an element, then layers, then specificity, and finally order of appearance. Specificity is fifth. Everything above it wins before the selector is even examined.

That inverts how the subject is usually taught. Specificity gets the calculators, the base-10 mnemonics and the arguments, and it decides a contest only once origin, importance, attachment and layers have all come out level. This site has a specificity calculator too, and it answers a genuinely different question: it tells you how two selectors compare, while this page tells you whether that comparison is ever reached.

The two pages share one engine for exactly that reason — the specificity numbers here are computed by the same module, so the two can never print different values for the same selector.

There is one more member of the list worth knowing about. Directly attached styles — a style attribute — sit at step three, above layers and above specificity. That is why an inline style beats an ID selector without being more specific than anything: it wins two steps earlier.

What this will not do

It reads a deliberately small slice of CSS: layer statements, layer blocks and ordinary rules. It is not a general CSS parser, so a media query, a container query, a nested rule or a supports block is skipped with a note rather than resolved. That keeps the page about the cascade rather than about parsing, and it means you should paste the competing rules rather than a whole stylesheet.

Two of the six steps are not applied, and both for the same reason: there is nothing to apply them to. Context needs shadow-tree boundaries, which a pasted stylesheet does not have. And two of the eight origin ranks are transition and animation declarations, which need something actually running. The full table is shown with those rows marked, so the omission is visible rather than silent.

It also does not know your document. The cascade only ever compares declarations that apply to the same element and the same property, and whether two selectors match the same element is a question about your HTML. The tool assumes everything you paste is in contention; if a rule never matches, it never enters the contest at all.

Finally, this resolves the cascade, not the whole path from stylesheet to rendered pixel. Inheritance, the revert and revert-layer keywords, and transitions all act after a winner is chosen, and none of them is modelled here.

Why is it free?

Reading CSS and sorting declarations is text work, and it runs in your browser. There is no server in the loop, so there is nothing to bill for and no account to create.

Nothing is uploaded and nothing is stored. Reload the page and it has forgotten your CSS.