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.