Design

Customization

Zen uses CSS custom properties (variables) for all design tokens, making it easy to customize the look and feel of your application. You can override these variables to match your brand or create entirely custom themes.

Overriding variables#

To customize Zen, override the CSS variables in your stylesheet. Variables defined on :root apply globally, while scoped selectors can target specific themes.

Creating a branded theme#

Here's an example of creating a custom branded theme with a blue accent:

CSS variable reference#

Primary#

The primary accent color used for primary buttons and branded elements.

VariableDescription
--zen-primaryPrimary/brand accent color (button backgrounds)
--zen-primary-fgText color on primary backgrounds

Surfaces#

Background colors for different elevation levels.

VariableDescription
--zen-surfacePrimary background (page level)
--zen-surface-raisedElevated surfaces (cards, modals)
--zen-surface-sunkenRecessed areas (inputs, wells)
--zen-surface-overlayOverlays (dropdowns, popovers)
--zen-surface-invertedInverted background (tooltips)
--zen-surface-disabledDisabled element background

Text#

Text colors for different emphasis levels.

VariableDescription
--zen-fgPrimary text (headings, body)
--zen-fg-mutedMuted text (labels, placeholders, hints)
--zen-fg-disabledDisabled text

Borders#

Border colors for different emphasis levels.

VariableDescription
--zen-borderDefault border (inputs, cards)
--zen-border-mutedSubtle borders (dividers)
--zen-border-strongEmphasized borders (focus, active)

Interactive states#

Colors for interactive elements like buttons, checkboxes, and list items.

VariableDescription
--zen-interactive-bgDefault interactive background
--zen-interactive-bg-hoverHover state background
--zen-interactive-bg-pressedPressed/active state background

Focus#

Focus ring styles for accessibility.

VariableDescription
--zen-focus-ringFocus ring color
--zen-focus-offsetFocus ring offset color (gap)

Status colors#

Colors for feedback states (info, success, warning, error).

VariableDescription
--zen-status-infoInfo accent color
--zen-status-info-bgInfo background
--zen-status-info-fgInfo text color
--zen-status-successSuccess accent color
--zen-status-success-bgSuccess background
--zen-status-success-fgSuccess text color
--zen-status-warningWarning accent color
--zen-status-warning-bgWarning background
--zen-status-warning-fgWarning text color
--zen-status-errorError accent color
--zen-status-error-bgError background
--zen-status-error-fgError text color

Typography#

Font family variables.

VariableDescription
--zen-font-familyDefault font stack
--zen-font-family-monoMonospace font stack

Using OKLCH colors#

Zen uses OKLCH color values for better color manipulation and perceptual uniformity. OKLCH colors are defined as oklch(lightness chroma hue):

  • Lightness: 0 (black) to 1 (white)
  • Chroma: 0 (gray) to ~0.4 (vivid)
  • Hue: 0-360 degrees (color wheel)

Tips#

  • Always provide both light and dark theme overrides for a consistent experience
  • Use OKLCH for colors to maintain perceptual consistency across themes
  • Test your customizations in both themes to ensure adequate contrast
  • Use browser DevTools to inspect and experiment with CSS variables in real-time

Token naming#

All Zen tokens use the --zen- prefix. Unsuffixed names represent the default value; variants add a suffix, such as --zen-border-muted. Foreground colors use fg, and background qualifiers use bg. The --zen-palette-50 through --zen-palette-950 tokens provide the selected neutral, slate, gray, zinc, or stone shades used by semantic colors.

Migrating token names#

Update custom overrides and utility classes to the names below. Token values and light/dark palette definitions are unchanged. The old names are no longer provided.

Previous tokenCurrent token
--zen-radius-default--zen-radius
--zen-shadow-default--zen-shadow
--zen-padding-x-default--zen-padding-x
--zen-padding-y-default--zen-padding-y
--zen-gap-default--zen-gap
--zen-surface-base--zen-surface
--zen-border-default--zen-border
--zen-text-primary--zen-fg
--zen-text-muted--zen-fg-muted
--zen-text-disabled--zen-fg-disabled
--zen-primary-foreground--zen-primary-fg
--zen-status-*-text--zen-status-*-fg
--zen-focus-ring-offset--zen-focus-offset
--zen-gray-*--zen-palette-*
Previous utilityCurrent utility
bg-surface-basebg-surface
text-surface-basetext-surface
text-foreground / text-foreground-primarytext-fg
text-foreground-mutedtext-fg-muted
text-foreground-disabledtext-fg-disabled
text-primary-foregroundtext-primary-fg
text-status-*-texttext-status-*-fg

The surface color prop value also changes: use backgroundColor="surface" instead of backgroundColor="surface-base". Responsive values and hover/focus/active variants use the same new names. border-edge and ring-offset-focus-offset remain unchanged.

The package's Tailwind preset and its own build now share one configuration, including the correct --zen- variable references.