Design Tokens

A design token is a named design decision: color-action-primary, space-4, font-size-body. Instead of #2563EB appearing in forty places across three codebases and a Figma file, one token holds the value and everything references it. Change the token, and the change propagates everywhere — including to platforms that share nothing else.

The value isn't just find-and-replace convenience. Tokens make design decisions explicit, enumerable, and reviewable. When the palette is a named set rather than whatever hex values accumulated over two years, you can audit it for contrast, generate a dark theme from it, ship it to iOS and Android from the same source, and tell whether a new design is using the system or inventing values.

The most consequential structural idea is the tiered token: a semantic layer between the raw values and the components. Get that right and theming, rebranding, and dark mode become configuration. Get it wrong and every theme is a fork.

TL;DR

Quick Example

The three tiers, and why the middle one matters:

Every dark-mode implementation that becomes a maintenance burden skipped the semantic tier. The component referencing --color-blue-600 directly has no way to become dark without being edited.

Core Concepts

The three tiers

The semantic tier is where theming, rebranding, and accessibility adjustments happen. Skipping it feels like removing indirection and actually removes the only place a theme can be expressed.

The component tier is genuinely optional and easy to overuse. Add it when a component needs a value that shouldn't move with the global semantic token — not as a default habit, or you end up with a token per CSS declaration.

Naming

The rule that matters: name by role, not by appearance. color-danger survives a rebrand to orange; color-red becomes a lie. space-4 describes a step in a scale; space-16px breaks when the base unit changes.

Be consistent about direction, too. bg and fg as a pair is clearer than mixing background, surface, and text across a set — the names are an API, and an inconsistent API gets misused.

Token types

Motion and z-index are the two most commonly missed. Uncontrolled z-index is how you get z-index: 99999 in a codebase, and untokenized animation durations are why an interface feels inconsistent in ways nobody can name.

The pipeline

outputReferences: true is worth knowing about: it emits --color-action-primary: var(--color-blue-600) rather than flattening to the hex, so the relationship survives into the CSS and runtime theme changes propagate correctly.

DTCG format

The Design Tokens Community Group format is the emerging interchange standard, and adopting it now means your tokens move between tools without a translation layer:

$value, $type, and $description are the core fields. Style Dictionary v4, Tokens Studio, and Figma variables all speak it, and $description doubles as your documentation source.

CSS custom properties

Custom properties cascade and are live at runtime, which is what makes them the right implementation for tokens. SCSS variables are compile-time substitutions — they can't theme a subtree, can't respond to a media query, and can't be changed by JavaScript.

Best Practices

Never let components reference primitives

This is the single most important rule in the entire topic. Enforce it with a lint rule if you can — primitive tokens should be effectively private to the semantic layer.

Use a constrained scale, not arbitrary values

A spacing scale of 4, 8, 12, 16, 24, 32, 48, 64 removes hundreds of individual decisions and produces visual rhythm for free. The moment padding: 13px appears, the scale has stopped being the system.

Generate, don't hand-maintain, platform outputs

The whole point is one source. Hand-copying values into an iOS constants file guarantees drift, and the drift is invisible until someone notices the app doesn't match the web.

Include descriptions

$description is the only documentation most tokens will get, and "when should I use color-fg-muted rather than color-fg-subtle?" is exactly the question that determines whether the system is used correctly.

Version tokens like an API

Token names are consumed by every product. Renaming one is a breaking change; removing one is worse. Use semver, deprecate before removing, and ship an alias during the transition. See Design Systems.

Validate accessibility in the pipeline

Add a build step that checks every foreground/background semantic pair for WCAG contrast and fails the build on a violation. Contrast is a property of the token set — checking it once at the source is far more reliable than auditing screens later.

Keep the primitive palette small

A palette with fourteen shades of gray is a palette where nobody knows which gray to use. Ship the steps you actually need, and add more only when a real use case demands one.

Put tokens in their own package

A versioned @company/tokens package that products depend on makes the dependency explicit, the version visible, and updates deliberate. Tokens copied into each product are tokens that will diverge.

Common Mistakes

No semantic tier

Naming by appearance

Hardcoding values alongside tokens

A token per CSS declaration

Encoding the value in the name

Manual sync between design and code

FAQ

Do I need design tokens for a small project?

CSS custom properties for color and spacing, yes — they cost nothing and make theming possible later. A full three-tier system with a build pipeline is overkill for one small app. The threshold for the full apparatus is multiple platforms, multiple themes, multiple products, or a design team that needs to change values without a code change.

Style Dictionary or Tokens Studio?

They complement each other. Tokens Studio is a Figma plugin where designers author and manage tokens, syncing to a Git repository. Style Dictionary is the build tool that transforms that source into platform outputs. Many teams use both: Tokens Studio for authoring, Style Dictionary for distribution. Figma's native variables are increasingly capable and reduce the need for a plugin for simpler setups.

How do tokens work with Tailwind?

Generate the Tailwind theme from your token source, so bg-action-primary and p-4 map to tokens rather than to Tailwind defaults. Tailwind v4's CSS-first configuration makes this cleaner — theme values are CSS custom properties, which is exactly what a token pipeline emits. See Tailwind.

How many tokens should we have?

Fewer than feels natural. A well-scoped system commonly has 20–40 semantic color tokens, 8–10 spacing steps, 6–8 type sizes, and a handful of radii and shadows. If picking a token requires deliberation, there are too many. Constraint is the feature — a system with a hundred color tokens has recreated the arbitrary-value problem with extra ceremony.

Should tokens be in the design system package or their own?

Their own, published separately. Native apps, marketing sites, email templates, and documentation all want tokens without wanting a React component library. A standalone @company/tokens package that the design system also depends on serves everyone.

How do we handle responsive values?

Two approaches. Either token names carry the breakpoint (font-size-heading-md, font-size-heading-lg) and components select, or the token value is fluid using clamp() so one token scales across viewports. Fluid typography with clamp() is elegant and reduces token count; explicit per-breakpoint tokens give more control. Fluid is the better default for type, explicit for layout spacing.

Related Topics

References