1:root { --brand: teal; }2@layer base, components;3@layer base {4 #shop h2 { color: navy; }5}6@layer components {7 .card__title {8 color: var(--brand); }9}index.htmlFresh tea#shop › .card › h2.card__title--brandteal2 · @layer components1 · @layer base#shop h2.card__title1,0,10,1,0teal#shop h2.card__titlevar(--brand)tealtomato
Left: the stylesheet (style.css) and its design token, --brandRight: the browser with the heading, and the cascade layers as a stairTokens: rules, specificity scores and values on their wayLeft: the stylesheet, with a design token on line 1 and two cascade layers, and the token's cell in front of it. Right: the browser showing the heading, and the two layers as a stair, base low and components high. Without layers, #shop h2 wins on specificity (1,0,1 beats 0,1,0) and the heading is navy. With @layer base, components; the later layer wins first, so .card__title's var(--brand) applies and the heading is teal. Changing only the token to tomato restyles the heading without touching any rule. A real browser runs the whole cascade at once, for every element and property. The figure splits it into steps: the first steps show the sheet without its layer lines, and the heading starts in the browser's default black until the first comparison. From then on, after every step the heading shows the colour a real browser would give that sheet.

The problem

  1. Big sites have thousands of rules written by many people. Here two of them set the colour of one heading, Fresh tea: an old page rule, #shop h2, and the card component's rule, .card__title.

Names and tokens

Cascade layers

One token, every part

What happens

;; step 1/9 · collide
the heading in index.html
  #shop › .card › h2.card__title
two rules match it, both set color
  #shop h2      color: navy
  .card__title  color: var(--brand)
which one wins?

A real browser runs the whole cascade at once, for every element and property. The figure splits it into steps: the first steps show the sheet without its layer lines, and the heading starts in the browser's default black until the first comparison. From then on, after every step the heading shows the colour a real browser would give that sheet. Styles outside any layer beat every layered style. That is why the heading stays navy while only components is wrapped, why the token on line 1 can stay unlayered, and why a site moving to layers puts its old rules in an early layer, as base is here. Wrap base first instead and the unlayered card rule would win at once.