Skip to main content

Search rules

Search all UI Guides rules by name, category, or source

designTailwind

Tokens Go in @theme, Not :root

MUST

MUST: Declare design tokens in `@theme`, not `:root` — a variable in `:root` is a working custom property but Tailwind never sees it, so it generates NO utilities and the codebase fills with `bg-[var(--brand)]` arbitrary values. `@theme { --color-brand: … }` generates `bg-brand`/`text-brand`/`border-brand`/`ring-brand` AND still emits the custom property for `var()`. The namespace prefix does the work: `--color-*` feeds color utilities, `--spacing-*` spacing, `--font-*` families, `--breakpoint-*` breakpoints. Nothing errors when you get it wrong.

Declare design tokens inside @theme so they generate utilities, instead of in :root where they only ever produce arbitrary values

/* generates nothing */ :root { --brand: oklch(0.62 0.19 259); }
/* generates bg-brand, text-brand, … */ @theme { --color-brand: oklch(0.62 0.19 259); }

Bad

Good

Why it matters

This is the most common v4 onboarding mistake, and it is invisible: nothing errors, nothing warns. You write `:root { --brand: #06c; }` because that is how CSS custom properties have always worked, and it does define a working variable — but Tailwind never sees it, so no `bg-brand` exists. The codebase then fills with `bg-[var(--brand)] text-[var(--brand)] border-[var(--brand)]`, arbitrary values that carry no variant ergonomics and no autocomplete, and every reviewer reads them as noise.

Move the same declaration into `@theme` under the right namespace — `@theme { --color-brand: oklch(0.62 0.19 259); }` — and Tailwind generates `bg-brand`, `text-brand`, `border-brand`, `ring-brand`, and the rest, while still emitting `--color-brand` as a real custom property that `var()` resolves anywhere. The namespace prefix is what does the work: `--color-*` feeds color utilities, `--spacing-*` spacing, `--font-*` families, `--breakpoint-*` breakpoints. A token in the wrong namespace, or in none at all, generates nothing.

Built by Gleb Stroganov, design engineer at Evil Martians.

The rules come from other people's skills and guidelines — Vercel, Rauno Freiberg, @Ibelick, impeccable, Emil Kowalski, Tailwind, RAMS — each one credited on the Sources page. The work here is extraction and wiring: every rule is pulled into one corpus, given a good and a bad example you can operate, a MUST/SHOULD/NEVER rule an agent can paste, and a link back to where it came from.