BuildUtilities

Design Tokens & CSS Variables Guide

What Are Design Tokens?

Design tokens are the atomic building blocks of a design system: named values that capture decisions like colors, spacing, typography, and shadows. Instead of hardcoding #3b82f6 everywhere, you define it once as --color-primary and reference the token.

This makes themes, dark mode, and brand updates trivially easy. Change the token, and every component updates automatically.

CSS Custom Properties (Variables)

CSS custom properties (often called CSS variables) are the browser-native way to implement design tokens:

:root {
  --color-primary: 221 83% 53%;     /* HSL values */
  --color-background: 0 0% 100%;
  --radius: 0.5rem;
  --shadow-sm: 0 1px 2px hsl(0 0% 0% / 0.05);
  --font-sans: 'Inter', system-ui, sans-serif;
  --spacing-unit: 0.25rem;
}

.dark {
  --color-primary: 217 91% 60%;
  --color-background: 222 47% 11%;
}

/* Usage */
.button {
  background: hsl(var(--color-primary));
  border-radius: var(--radius);
  font-family: var(--font-sans);
}

Token Categories

A well-structured design system organizes tokens into layers:

  • Primitive tokens: raw values, --blue-500: 221 83% 53%
  • Semantic tokens: purpose-based, --color-primary: var(--blue-500)
  • Component tokens: scoped to components, --button-bg: var(--color-primary)

This layering lets you swap entire themes by reassigning semantic tokens without touching components.

Tailwind CSS Integration

Tailwind CSS works beautifully with CSS variables. Define tokens in your CSS, then reference them in tailwind.config:

// tailwind.config.ts
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: 'hsl(var(--color-primary))',
        background: 'hsl(var(--color-background))',
        foreground: 'hsl(var(--color-foreground))',
      },
      borderRadius: {
        DEFAULT: 'var(--radius)',
      },
    },
  },
};

Convert between Tailwind and vanilla CSS with the Tailwind to CSS and CSS to Tailwind converters.

Building a Color System

A good color system needs scales (50–950), semantic mappings, and proper contrast in both light and dark modes:

:root {
  /* Primitive scale */
  --blue-50:  210 100% 97%;
  --blue-100: 210 100% 94%;
  --blue-500: 221 83% 53%;
  --blue-900: 224 76% 28%;

  /* Semantic mapping */
  --color-primary: var(--blue-500);
  --color-primary-foreground: 0 0% 100%;
  --color-muted: 210 40% 96%;
  --color-muted-foreground: 215 16% 47%;
}

.dark {
  --color-primary: var(--blue-400);
  --color-muted: 217 33% 17%;
  --color-muted-foreground: 215 20% 65%;
}

Generate complete color scales with the Color Scale Generator or full themes with the CSS Variables Theme Generator.

Spacing & Sizing Tokens

Consistent spacing creates visual rhythm. Use a base unit multiplied by a scale:

:root {
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-12: 3rem;     /* 48px */
  --space-16: 4rem;     /* 64px */
}

Dark Mode with Tokens

The best dark mode strategy: define all colors as semantic tokens, then swap them in a .dark class or prefers-color-scheme media query. Components never reference raw colors, only tokens.

This means you can add themes (high contrast, sepia, brand variations) just by creating new token sets.

Related Tools

Try These Tools

Related Documentation

Tip Jar