Color
Every colour class follows the same shape. Read this for the groups and rungs behind backgrounds, foregrounds, borders and dividers.
Every colour class follows the same shape, <prefix>-<group>-<rung>[-<state>].
The group is either surface, which covers page and container chrome, or one
of the intents: primary, secondary, accent, danger, success,
warning, neutral and disabled.
Backgrounds
Backgrounds are bg-<group>-<rung>[-<state>] on the intent groups, and
bg-surface-<tier> on the grounds.
bg-surface-low
bg-surface-base
bg-surface-high
bg-surface-higher
bg-surface-dimmer
<div class="bg-surface-low"></div>
<div class="bg-surface-base"></div>
<div class="bg-surface-high"></div>
<div class="bg-surface-higher"></div>
<div class="bg-surface-dimmer"></div>
Every rung is drawn twice from the one authored ramp: light on the left, dark on the right. Nothing here is a second palette.
primary
bg-primary-solidAaAabg-primary-mutedAaAabg-primary-subtleAaAa
accent
bg-accent-solidAaAabg-accent-mutedAaAabg-accent-subtleAaAa
danger
bg-danger-solidAaAabg-danger-mutedAaAabg-danger-subtleAaAa
success
bg-success-solidAaAabg-success-mutedAaAabg-success-subtleAaAa
warning
bg-warning-solidAaAabg-warning-mutedAaAabg-warning-subtleAaAa
<button class="bg-primary-solid hover:bg-primary-solid-hover active:bg-primary-solid-active">
Solid
</button>
<button class="bg-primary-muted hover:bg-primary-muted-hover">Muted</button>
<button class="bg-primary-subtle hover:bg-primary-subtle-hover">Subtle</button>
Of those, solid, muted and subtle each come with a -hover and an
-active step.
Foregrounds
Prose ink is text-surface[-<rung>], intent ink is text-<group>-<rung>, and
ink that sits on a filled ground is text-<group>-on-<rung>.
The quick brown fox jumps over the lazy dog. text-surface
The quick brown fox jumps over the lazy dog. text-surface-muted
The quick brown fox jumps over the lazy dog. text-surface-subtle
The quick brown fox jumps over the lazy dog. text-surface-link
The quick brown fox jumps over the lazy dog. text-accent-solid
The quick brown fox jumps over the lazy dog. text-danger-solid
The quick brown fox jumps over the lazy dog. text-success-solid
The quick brown fox jumps over the lazy dog. text-warning-solid
<p class="text-surface">Primary prose ink</p>
<p class="text-surface-muted">Muted prose ink</p>
<p class="text-surface-subtle">Subtle prose ink</p>
<span class="bg-danger-solid text-danger-on-solid">Ink on a fill</span>
The pairing between a fill and its ink is resolved in the token layer, so as
long as you pair an on-* rung with the matching background, both survive
every theme and both colour modes.
<span class="bg-primary-solid text-primary-on-solid">Save</span>
<span class="bg-primary-muted text-primary-on-muted">Save</span>
<span class="bg-primary-light text-primary-on-light">Save</span>
Borders and dividers
Borders are border-<group>-<rung>, with the per-side variants border-t-*,
border-b-*, border-r-* and border-l-*, plus divide-* for children.
<div class="border border-surface rounded-surface-sm">
<ul class="divide-y divide-surface">
<li>One</li>
<li>Two</li>
</ul>
</div>
Border colour is the one family where the surface group carries no rung at all:
border-surface is the whole of it, and border-surface-base matches nothing.
The intents stop at subtle, as in border-danger-subtle. If you need an edge
to be opaque, put a background behind a hairline instead of looking for an
opaque border colour.
Limitations
Generated colour utilities have no slash modifier, so bg-accent-solid/40
matches no candidate and Tailwind emits no rule at all.
We dropped the modifiers because they were inconsistent and because they
compounded. They only ever worked on bg-* and text-* while border-* and
divide-* refused the same syntax, and on a rung that is already translucent
they stacked, so bg-primary-subtle/40 came out as 40 % of a fill that is
mostly transparent to begin with.
If you want something lighter, reach for a lower rung. Opacity that is part of the design belongs in the token tree, where it has a name and flips with the colour mode.
<div class="bg-accent-solid">Full</div>
<div class="bg-accent-muted">Stronger overlay</div>
<div class="bg-accent-subtle">Lighter overlay</div>
The generated families take over the bg-, text-, border- and divide-
prefixes but leave Tailwind’s arbitrary-value syntax alone, so a genuine
one-off still compiles in brackets.
<div class="bg-[color-mix(in_oklab,var(--mirror-bg-accent-solid)_40%,transparent)]"></div>
Tailwind’s own colour scale is turned off, since --color-*: initial is set in
the generated theme block and bg-red-500 therefore doesn’t exist. Every colour
a theme can move is already in the families above.
Token values flip with the colour mode on their own, so bg-surface-base is
already correct in both and writing dark: is rarely necessary. Reach for the
variant only when a mode needs different tokens, which is covered in
Theming.