A practical guide to design tokens

How we structure color, spacing, and type as tokens so a brand system actually survives contact with real engineering.

  • Web Design
  • Engineering

A design system is only as good as its weakest handoff, and the weakest handoff is almost always "here's a hex code, use it wherever." Tokens exist to close that gap.

Primitives vs. semantic tokens

The pattern that holds up longest is a two-layer one: raw primitives (a color scale, a spacing scale), and semantic tokens that reference them by purpose rather than value.

:root {
	/* primitive */
	--color-gray-900: #111827;

	/* semantic — what components actually use */
	--color-text: var(--color-gray-900);
}

Components should only ever reach for the semantic layer. When a rebrand or a dark mode comes along, you repoint the mapping once, in one file, and every component that used --color-text updates without a single line of component code changing.

Sizing tokens, not just color

The same idea applies to spacing and type — a component sets its own scale once, then sizes everything inside it relative to that, so nudging one value rescales the whole component predictably instead of requiring a find-and-replace across dozens of files.

Where this breaks down

Tokens fail when there are too many of them, named too specifically — --button-primary-hover-dark-mode-border is not a token, it's a variable pretending to be one. Keep the vocabulary small and the purpose obvious, and resist adding a new token until something is genuinely reused in a second place.

If you're mid-rebuild and want a second pair of eyes on your token structure, we're happy to help.