Skip to content

Dark theme

Activated via [data-theme="dark"] on <html> or any subtree. Light is untouched. Matter's warm-neutral palette inverts cleanly:

Flip the theme — live

Side-by-side

light

Card title

Surface · elevated · hairline · primary ink. Token names resolve through both modes.

dark

Card title

Surface · elevated · hairline · primary ink. Token names resolve through both modes.

Token rebind

TokenLightDark
--surface-page#FFFFFF#0D0D0D
--surface-elevated#FFFFFF#1A1815
--text-primary#0D0D0D#F4F1EC (warm white, never #FFF)

Bloom palette stays — reads as ambient warmth on dark. Each bloom drops α by ~30%.

The dark contract

The semantic ring (--surface-*, --text-*, --line-*, --shadow-*) rebinds under [data-theme="dark"]. Components author only against the ring. Authoring against primitives (var(--peach-3) from a component) breaks the dark contract.

Imports

@import "@matter/tokens/css";           /* primitives */
@import "@matter/tokens/css/canonical"; /* semantic ring — light defaults */
@import "@matter/tokens/css/dark";      /* dark overrides on [data-theme="dark"] */
Consume the semantic ring exclusively. Flipping data-theme repaints everything correctly.
Don't reference #FFF or primitive tokens directly from a component. Both break the dark theme.

On this page