Back to work
snippet//1 min read

Design Tokens That Scale

How to architect CSS custom properties for a design system that works across light mode, dark mode, and beyond.


Design tokens are the atoms of your visual language. Get them right, and your entire system becomes composable and consistent. Get them wrong, and you'll spend hours chasing color inconsistencies.

The semantic layer

The mistake most people make is mapping tokens directly to raw values:

/* Don't do this */
--blue-500: #3b82f6;
--gray-900: #111827;

Instead, create a semantic layer that describes intent:

:root {
  --text-primary: #1c1917;
  --text-secondary: #57534e;
  --bg: #fafaf9;
  --border: #e7e5e4;
}

.dark {
  --text-primary: #fafaf9;
  --text-secondary: #a8a29e;
  --bg: #0c0a09;
  --border: #292524;
}

Now your components reference intent, not color. Theming becomes trivial.

Transition tokens

One often-overlooked category: motion tokens. Define your timing curves and durations as tokens:

:root {
  --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
}

This ensures consistent motion across every component without remembering magic numbers.

The payoff

With semantic tokens, adding a new theme (high contrast, sepia, brand-specific) is just adding a new set of custom property values. No component changes needed.