Color Model: OKLCH

Espalier uses OKLCH as its internal color model. OKLCH describes colors using three axes: L (perceived lightness, 0–1), C (chroma / color intensity, 0–0.37+), and H (hue angle, 0–360).

This model drives the entire palette generation pipeline: seed color input, color-theory variant generation, semantic token derivation, and APCA contrast enforcement all operate in OKLCH before values are emitted as CSS custom properties.

What this means when writing theme colors

You can provide the seedColor theme field in any valid CSS color format. OKLCH is the most direct:

// Any of these are valid seed colors
{ seedColor: 'oklch(0.65 0.18 240)' }  // OKLCH — direct
{ seedColor: '#3b82f6' }               // hex — converted internally
{ seedColor: 'hsl(217 91% 60%)' }      // HSL — converted internally

Using OKLCH directly gives you the most predictable results because the numbers you write correspond to perceived brightness (L) and color intensity (C) rather than hardware channel values.

OKLCH in application CSS

Because --esp-color-* tokens are emitted as OKLCH values, you can use Relative Color Syntax to derive related values in your own CSS:

/* Lighten a token by shifting its L channel */
background: oklch(from var(--esp-color-primary) calc(l + 0.05) c h);

/* Desaturate by reducing chroma */
color: oklch(from var(--esp-color-text) l calc(c * 0.5) h);

Lightness ramp tokens

Espalier also exposes the raw lightness values it uses internally as --esp-l-* tokens (e.g. --esp-l-surface, --esp-l-text). These are useful when you need to apply the same perceptual lightness levels to custom colors that are outside the standard palette.

Components API Guides Getting started Styling Espalier Browser support GitHub npm package Taproot I/O