Skip to content
ZeroServer.tools
All guides

CSS Custom Properties: A Practical Guide to Design Tokens

June 5, 2026 · 3 min read

CSS custom properties — commonly called CSS variables — are one of the most powerful additions to CSS in years. They let you define a value once and reuse it everywhere, making theming, dark mode, and design consistency far easier to maintain.

What are CSS custom properties?

A custom property is any property whose name starts with two dashes (--). You define it on an element (usually :root so it's global) and read it with var():

:root {
  --color-primary: #6366f1;
  --spacing-md: 1rem;
}

.button {
  background: var(--color-primary);
  padding: var(--spacing-md);
}

Unlike preprocessor variables (Sass $var, Less @var), CSS custom properties are live — they can be changed at runtime with JavaScript and they cascade like any other CSS property. That makes them the right choice for themes, user preferences, and dynamic values.

Building a color scale

A design token system usually starts with a colour palette. A common approach — used by Tailwind CSS and most modern design systems — is to define 10 shades per colour from very light (50) to very dark (900), keeping the hue and saturation constant while varying the lightness:

:root {
  --primary-50:  #eef2ff;
  --primary-100: #e0e7ff;
  --primary-200: #c7d2fe;
  --primary-300: #a5b4fc;
  --primary-400: #818cf8;
  --primary-500: #6366f1;  /* base */
  --primary-600: #4f46e5;
  --primary-700: #4338ca;
  --primary-800: #3730a3;
  --primary-900: #312e81;
}

You can generate a full 10-shade CSS variable scale for any colour instantly with the CSS Variables Generator. Pick your brand colour, name the variable, and copy the ready-to-paste :root block.

Typography tokens

Beyond colours, font stacks are a great candidate for tokens:

:root {
  --font-sans:  system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono:  ui-monospace, 'Cascadia Code', Menlo, Consolas, monospace;
  --font-size-base: 1rem;
  --line-height-base: 1.6;
}

The Font Stack Generator has ready-to-copy CSS font-family declarations for system UI, geometric sans, traditional serif, monospace, and more — with a live preview of each stack.

Spacing and sizing tokens

:root {
  --spacing-1: 0.25rem;
  --spacing-2: 0.5rem;
  --spacing-4: 1rem;
  --spacing-8: 2rem;
  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 1rem;
}

A consistent spacing scale (often multiples of 4px) means every gap, padding, and margin in your design is drawn from the same set of values — making the UI feel cohesive and making spacing decisions easier.

Dark mode with custom properties

Custom properties cascade, which means a child element can redefine them. This makes dark mode trivial:

:root {
  --color-surface: #ffffff;
  --color-on-surface: #1c1c1e;
}

[data-theme="dark"] {
  --color-surface: #1c1c1e;
  --color-on-surface: #ffffff;
}

Every component that uses var(--color-surface) automatically flips when you toggle the data-theme attribute — no component-level changes needed.

Generating harmonious colour palettes

Beyond a single-hue scale, you often need multiple related colours — an accent, a success green, a warning amber. The Color Palette Generator lets you pick a base colour and generate a complementary, analogous, triadic, or tetradic scheme using colour theory. Feed the resulting HEX values back into the CSS Variables Generator to produce full 10-shade scales for each.

For exploring individual shades, the Color Shades Generator lets you see tints and shades of any colour at a glance — useful for picking the exact token values before committing them to your design system.

A minimal design token starter

Here is a minimal but complete token set you can drop into any project:

:root {
  /* Colours */
  --clr-primary-500: #6366f1;
  --clr-neutral-100: #f5f5f5;
  --clr-neutral-900: #171717;

  /* Typography */
  --font-body:  system-ui, sans-serif;
  --font-code:  ui-monospace, 'Courier New', monospace;
  --text-sm:    0.875rem;
  --text-base:  1rem;
  --text-lg:    1.25rem;

  /* Spacing */
  --space-2:  0.5rem;
  --space-4:  1rem;
  --space-8:  2rem;

  /* Shape */
  --radius:   0.5rem;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.1);
}

Start small, add tokens as you notice yourself repeating values, and resist the urge to token-ify everything upfront. CSS custom properties are live and cascade — you can always add more later without breaking what you've already built.