Chrome & temperature
The neutral room of surfaces, ink, and borders, and the three knobs that tint it warm or cool.
Chrome is the neutral room that every component sits in, and this page shows how to leave it
gray, tint it warm or cool, and see what the tint does to each surface. Brand color
(--brand-primary, --brand-secondary, and the status colors) sits on top of the room, and
paper temperature changes only the room.
What chrome is
The room is a set of roles, each with a utility.
| Role | Tokens | Utilities |
|---|---|---|
| Surfaces | --sys-bg, --sys-surface, --sys-surface-raised, --sys-surface-sunken | bg-background, bg-surface, bg-surface-raised, bg-surface-sunken |
| Ink | --sys-fg, --sys-fg-muted, --sys-fg-subtle | text-fg, text-fg-muted, text-fg-subtle |
| Lines | --sys-border, --sys-border-strong | border-border, border-border-strong |
| Effect ink | --sys-contrast | bg-contrast, and the focus ring |
Each --sys-* role takes its lightness from a --chrome-* token, which holds the light value
at :root and the inverted value under .dark, and adds chroma and hue on top. The neutral
ramp (--neutral-*) has no chroma, so with no knobs set the room is gray.
Gray, warm, and cool
A look tints the room by setting three knobs. The chroma knob takes the curve described below
for surfaces, ink, and lines. The tag knob is a flat value for the categorical tag colors
(--sys-cat-*), and the hue knob is shared.
| Paper | Knobs a look sets | Result |
|---|---|---|
| Gray | none | The room is achromatic. |
| Warm | --chrome-chroma: var(--warm-chroma), --chrome-chroma-tag: var(--warm-chroma-tag), --chrome-hue: var(--warm-hue) | A warm tint at hue 72. |
| Cool | --chrome-chroma: var(--cool-chroma), --chrome-chroma-tag: var(--cool-chroma-tag), --chrome-hue: var(--cool-hue) | A blue-gray tint at hue 230. |
Washi, ICS, and Ramson all set the warm knobs, and no prefab is cool.
To use cool paper, or warm paper under your own colors, set the knobs on your own
[data-theme].
[data-theme="acme"] {
--chrome-chroma: var(--cool-chroma);
--chrome-chroma-tag: var(--cool-chroma-tag);
--chrome-hue: var(--cool-hue);
}system.css repaints every --sys-* surface from these knobs wherever a [data-theme] is
set, so the three lines above are all a look has to say. The sidebar paper picker in these
docs is a docs-only axis, and app/global.css maps its data-chrome attribute to the same
knobs. An installed kit responds to [data-theme] and ships no values for data-chrome.
The curve
Warm and cool share one curve and differ in hue and peak. In the formula, l is the lightness
of the underlying --chrome-* role, taken from the neutral ramp.
chroma(l) = base + peak × (1 − l) × l
--sys-role = oklch(from var(--chrome-role) l chroma(l) hue)| Hue | Base | Peak | Tag chroma | |
|---|---|---|---|---|
| Warm | 72 | 0.0042 | 0.05 | 0.012 |
| Cool | 230 | 0.0042 | 0.048 | 0.012 |
The curve falls to the 0.0042 base at the lightest and darkest steps and reaches about 0.017 at
mid lightness, so mid-lightness roles such as borders and muted ink carry more tint than the
near-white surfaces do. The tag chroma
(--warm-chroma-tag and --cool-chroma-tag) is one flat value, because a categorical chip
wants the same warmth at every lightness. The curves and tag values live in
registry/dry/tokens/system.css.
Dark paper
.dark swaps the lightness on each --chrome-* role, and the same knobs tint the result, so a
warm look is warm in both modes. Put .dark on the same element as data-theme.
What is guaranteed
These hold on gray, warm, and cool paper in light and dark. Paper changes chroma and hue and never lightness, so a paper never moves them.
text-fgandtext-fg-mutedpass AA text contrast onbg-background,bg-surface,bg-surface-raised, andbg-surface-sunken.- The unfilled edge of a control (
--sys-track, used by the switch rail and the checkbox and radio border) is a light edge by choice, under the WCAG 1.4.11 line, so the control's shape and label carry its state. - The focus ring is
--sys-contrast, a solid ink opposite the surfaces, so it flips with light and dark and does not depend on the brand.
text-fg-subtle is the faintest ink, and it does not reliably pass AA, more so in dark. Use it for
text a reader does not depend on.
Try it
The cards below pin the room to cool, base, and warm paper, in light and dark. They keep the brand that the sidebar has selected, so only the room changes between cards. The ramp strips set the paper curve against a reference palette on the same lightness ramp.
Figma Vellum reference vs warm chrome on the dry achromatic L ramp.
Slate blue-gray reference vs cool chrome on the same L ramp.
—
Body ink on canvas. Muted sits lower. Subtle is the faintest.
—
—
Body ink on canvas. Muted sits lower. Subtle is the faintest.
—
—
Body ink on canvas. Muted sits lower. Subtle is the faintest.
—
—
Body ink on canvas. Muted sits lower. Subtle is the faintest.
—
—
Body ink on canvas. Muted sits lower. Subtle is the faintest.
—
—
Body ink on canvas. Muted sits lower. Subtle is the faintest.
—
Next
Set the brand on top of the room on Retune, or start from a whole look on Prefabs. Specimens for each surface and ink are on Color.