Agent Wranglers

Required

Declare the layer order once

Declare every cascade layer in one @layer statement at the top of the entry file. Put every style inside a named layer, so no style is left unlayered.

How to do it

Styles outside any layer beat all layered styles, whatever their specificity. One forgotten file can then override every component. List the layers once, as in Sort styles into five layers, and import each file into its layer. A file may not invent a new layer name.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

CSS example

/* The first line of the entry file. Order is fixed here and nowhere else. */
@layer tokens, base, layout, components, utilities;

@import url("components/booking-form.css") layer(components);

JavaScript example

// Build check: names used in layer() or @layer must be declared in the first statement
import { readFileSync } from 'node:fs';
const css = readFileSync('dist/main.css', 'utf8');
const declared = /^@layer ([^;{]+);/.exec(css)?.[1].split(',').map(name => name.trim()) ?? [];
const used = [...css.matchAll(/@layer\s+([\w-]+)\s*\{|layer\(([\w-]+)\)/g)].map(m => m[1] || m[2]);
const unknown = used.filter(name => !declared.includes(name));
unknown.forEach(name => console.log(`FAIL layer "${name}" is not in the declared order`));
process.exit(declared.length && !unknown.length ? 0 : 1);

Python example

# The same check in Python
import re, sys
css = open("dist/main.css").read()
first = re.match(r"@layer ([^;{]+);", css)
declared = [name.strip() for name in first.group(1).split(",")] if first else []
used = [a or b for a, b in re.findall(r"@layer\s+([\w-]+)\s*\{|layer\(([\w-]+)\)", css)]
unknown = [name for name in used if name not in declared]
for name in unknown:
    print(f'FAIL layer "{name}" is not in the declared order')
sys.exit(0 if declared and not unknown else 1)

How to check

The first statement of the entry file is one @layer list. Every other @layer or layer() name in the project appears in that list. The built CSS has 0 declarations outside a layer.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. Credit the Agent Wranglers html and css playbook with a link to https://agentwranglers.se/playbook/html-css/the-cascade/declare-layer-order-once. Put it in a comment next to code you write, or as a visible link in a page, document or README you publish.