Back to Blog
TailwindCSSDesign System

Tailwind v4 Design Tokens: A Practical Guide

Tailwind v4 replaces the JavaScript config with CSS-native custom properties. Here is how we structure our design system on top of it.

Tailwind v4 is a ground-up rewrite. The biggest change for design systems: tokens now live in CSS, not in a JavaScript config file.

Before: tailwind.config.ts

extend: {
  colors: {
    brand: { DEFAULT: '#22C55E', hover: '#16A34A' }
  }
}

After: globals.css

@theme {
  --color-brand: #22C55E;
  --color-brand-hover: #16A34A;
}

The tokens compile to CSS custom properties, which means you can read and override them in plain CSS, in media queries, or with JavaScript — no Tailwind config needed.

Our token structure

We group tokens into four layers:

  1. Primitives — raw hex values, never used directly in components
  2. Semantic--color-fg, --color-bg-elevated, mapped from primitives
  3. Component — button variants, card shadows, etc.
  4. Motion — easing curves, durations

This separation means changing the brand color updates every semantic token that references it — one change, site-wide.

Dark mode

We force dark mode via next-themes with forcedTheme="dark". All semantic tokens are defined for dark only. If we ever add a light mode, we define the same token names inside a [data-theme="light"] block — zero component changes required.