revert vs revert-layer vs unset in Cascade Layers

Five CSS-wide keywords can each be described as “resetting” a property, and in a layered stylesheet they produce five different computed values from the same declaration. Choosing by feel is how a reset ends up applying Times New Roman to a card. This page gives a decision procedure that resolves the choice in one pass, extending revert-layer and cascade rollback under the CSS cascade fundamentals reference.

Prerequisites

You need to know how layer declaration order works and to be able to tell whether a property is inherited — MDN lists this under “Inherited: yes/no” on every property page. The canonical stack is used throughout:

/* WHY: three populated layers give the keywords something to differ about;
   with a single layer, revert and revert-layer produce the same answer. */
@layer reset, base, theme, components, utilities;

Tooling: DevTools with the Computed tab. No build step.

Step 1: Say what value you want, in words

Every mistake in this area starts with skipping this step. Write the sentence first:

  • “the parent’s value” → inherit
  • “the value CSS specifies as this property’s default” → initial
  • “whichever of those two the property normally uses” → unset
  • “the browser’s default styling for this element” → revert
  • “whatever my lower layers say” → revert-layer

What this does: turns a keyword choice into a lookup instead of a guess.

What each CSS-wide keyword computes to A table with five keyword rows — initial, inherit, unset, revert and revert-layer — and two result columns showing the computed outcome for an inherited property such as color and a non-inherited property such as padding. keyword inherited property (color) non-inherited (padding) initial canvastext (spec default) 0px inherit the parent's colour the parent's padding unset = inherit → parent's colour = initial → 0px revert UA value, else inherited UA value, else 0px revert-layer the next layer down's colour the next layer down's padding

Step 2: Check whether the property inherits

unset is the only keyword whose meaning changes with the property, and that is exactly what makes it dangerous in a reset.

@layer components {
  .note {
    /* WHY: `color` is inherited, so `unset` here means "inherit" — the note
       takes the parent's colour, NOT the theme layer's colour. */
    color: unset;

    /* WHY: `padding` is not inherited, so `unset` means "initial" — 0px,
       discarding every author layer including the design system's spacing. */
    padding: unset;
  }
}

What this does: demonstrates why one keyword produced two unrelated behaviours in a single rule. If you cannot state which branch applies without checking, use an explicit keyword instead.

Step 3: Locate the layer that holds the value you want

revert-layer steps down exactly one layer at a time — it does not search for a value you name.

@layer base       { .note { padding: 4px; } }
@layer theme      { .note { padding: 8px; } }
@layer components { .note { padding: 16px; } }

@layer utilities {
  /* WHY: this lands on `components` (16px), not on `theme` (8px). To reach
     `theme`, the components declaration would have to not exist — a rollback
     cannot skip a layer that contributes a value. */
  .note { padding: revert-layer; }
}

What this does: confirms the rollback destination before you rely on it. When the value you want is two layers down, the answer is to restructure — move the intermediate declaration, or set the value explicitly — not to reach for a different keyword.

Step 4: Apply the decision table

You want Keyword Reaches
The parent element’s value inherit The DOM, not the cascade
The property’s spec default initial Nothing in your CSS
Default behaviour for this property type unset Parent or spec default
The browser’s own styling revert The user-agent origin
Your lower layers’ value revert-layer One layer down

What this does: resolves the choice. Note the asymmetry worth remembering: only revert-layer is aware that layers exist at all. The other four were defined before layers shipped and treat your entire author stack as a single undifferentiated block.

What each keyword can reach A central author-origin box containing four stacked layers. Arrows leave it toward four destinations: the DOM parent for inherit, the spec default for initial, the user-agent origin for revert, and an internal arrow inside the author box for revert-layer. author origin utilities components theme base revert-layer stays inside the stack user-agent origin revert spec default initial · unset (non-inherited) DOM parent inherit · unset

Step 5: Prove the result in the Computed tab

A page that looks right is not proof — several of these keywords coincide in the common case where only one layer sets the property.

Why the inline-style probe cannot test revert-layer An inline style attribute sits outside the layer system, so a revert-layer written there has no previous author layer to fall back to and behaves as revert, reaching the user-agent origin instead of the layer below. el.style.padding = 'revert-layer' inline — outside every layer behaves as revert → user-agent value @layer utilities { padding: revert-layer } a real rule, inside a layer steps down one layer → components value Use the console probe to compare initial, inherit, unset and revert — but test revert-layer from a real rule, or the probe silently measures the wrong keyword.
// Print the resolved value for each candidate keyword on the same element by
// applying them one at a time. Run in the console with the element selected
// as $0 in DevTools.
['initial', 'inherit', 'unset', 'revert', 'revert-layer'].forEach((kw) => {
  const prev = $0.style.padding;
  $0.style.padding = kw;                       // inline style: highest priority
  console.log(kw.padEnd(12), getComputedStyle($0).paddingTop);
  $0.style.padding = prev;                     // restore
});

What this does: produces five concrete values for one element in one run. Note the inline-style caveat: because the probe writes to element.style, a revert-layer there behaves as revert — inline styles are unlayered. Use it to compare initial, inherit, unset and revert, and test revert-layer from a real rule inside a layer.

Verification

  1. In the Styles panel, confirm the winning declaration is the one you edited and that its layer annotation matches the layer you intended.
  2. In the Computed tab, read the resolved value and compare it with the sentence you wrote in Step 1. They should match exactly.
  3. Toggle the lower layer’s declaration off. revert-layer should change its result; revert, initial and unset should not. That difference is the definitive test of which keyword you actually got.

Troubleshooting

unset produced a value from outside my design system. : The property is not inherited, so unset resolved to the spec initial value and discarded every author layer. Use revert-layer when the design system’s own lower-layer value is what you want.

revert restored a browser default I did not expect to exist. : The user-agent stylesheet styles more than most people assume — display, margin, font, list-style, form-control appearance. revert returns all of it. If you only wanted to drop your own top layer, revert-layer is the keyword.

revert-layer and revert behave identically. : The declaration is in the lowest layer, or in unlayered CSS. In both positions there is no previous author layer, so the rollback continues into the previous origin. Move the rule up a layer if you want a different result.

The keyword had no effect whatsoever. : A higher-priority declaration is winning — an !important, an unlayered rule, or an inline style. Every CSS-wide keyword is an ordinary declaration and loses the same cascade competitions as any value.

inherit produced nothing visible on a root-level element. : inherit on an element whose parent has no computed value for that property falls through to the initial value. It is not a cascade tool at all; it reads the DOM.

Complete working example

/* ============================================================
   One element, five keywords — copy into a page and inspect
   ============================================================ */
@layer reset, base, theme, components, utilities;

@layer base {
  /* WHY: a value in a low layer gives revert-layer somewhere to land. */
  .swatch { padding: 4px; color: #6b5e3e; border: 1px dotted #d4c89a; }
}

@layer theme {
  .swatch { padding: 8px; color: #5a6830; }
}

@layer components {
  /* The layer directly below `utilities` — the rollback destination. */
  .swatch { padding: 16px; color: #3b3522; }
}

@layer utilities {
  /* WHY: each modifier isolates one keyword so the computed values can be
     compared side by side in DevTools. */
  .swatch--initial     { padding: initial; }      /* → 0px */
  .swatch--inherit     { padding: inherit; }      /* → the parent's padding */
  .swatch--unset       { padding: unset; }        /* → 0px (not inherited) */
  .swatch--revert      { padding: revert; }       /* → the UA default, 0px */
  .swatch--rollback    { padding: revert-layer; } /* → 16px, from components */

  /* WHY: colour IS inherited, so the same five keywords diverge differently —
     this is the pair that exposes `unset`'s dual personality. */
  .swatch--c-unset     { color: unset; }          /* → the parent's colour */
  .swatch--c-rollback  { color: revert-layer; }   /* → #3b3522, from components */
}

Frequently Asked Questions

Is unset ever the right choice inside a cascade layer?

Yes — when the intent really is “behave as though no author rule had touched this element”. That is a legitimate need for content coming from outside your system, where inherited properties should flow from the container and non-inherited ones should return to their defaults. The moment your intent involves the word “back to our base styles”, unset is wrong, because it is blind to your layer stack.

Why does revert produce different results on inherited and non-inherited properties?

The keyword itself is consistent: it removes the author origin’s contribution and lets the cascade continue from there. What differs afterwards is inheritance. An inherited property with no user-agent rule then takes the parent’s computed value, while a non-inherited one settles on its initial value. The variation comes from the properties, not from the keyword.

Can revert-layer replace every use of !important in an override layer?

It replaces the large majority — every override whose purpose was to cancel a declaration from a lower layer. Two cases survive: an existing !important in another layer, which only an !important rollback can beat, and unlayered author styles, which outrank every layer no matter which keyword you use. Both are better fixed by moving the offending rules into layers than by escalating.

Up: revert-layer and Cascade RollbackCSS Cascade Fundamentals & @layer Syntax