Skip to content
Book a call
Design Engineering

Design tokens explained for product teams

A plain explanation of design tokens: what they are, how to name them, how they move from Figma variables to CSS and what to do first in an existing product.

MD Rakib Shekh6 min read

Design tokens sound technical. The idea is simple, though, and it can save a team a lot of time.

A design token is a name for a design decision. Instead of writing #1F4FE0 in forty places, you write color-action and define it once. Change the definition, and every place that uses the name changes with it.

That is all a token is. The rest of this article is how to use them well, as a designer or a developer on the same team.

What a token is

A token has a name and a value. The value can be a color, a size, a font, a radius, a shadow or a time for an animation.

Here is a small example in CSS:

:root {
  --color-action: #1f4fe0;
  --space-4: 16px;
  --radius-md: 8px;
}

.button {
  background: var(--color-action);
  padding: var(--space-4);
  border-radius: var(--radius-md);
}

The button never says what blue it is. It says "use the action color". That small step gives you three things:

  • Consistency. Every button uses the same blue, because there is only one definition.
  • Fast change. A rebrand, a new theme or a dark mode becomes a change of values, not a search through every file.
  • A shared language. The designer says "action color" and the developer knows exactly which variable that is.

Primitive, semantic and component tokens

Most teams end up with three layers. You do not need all three on day one, but it helps to know where you are heading.

Primitive tokens

These are the raw palette. They describe what a value is: blue-500, gray-100, space-16. They have no meaning yet. They are a menu of choices.

Semantic tokens

These describe what a value is for: color-text-primary, color-surface, color-border-subtle, color-action. Each one points to a primitive. color-action might point to blue-500 today.

This is the layer designers and developers use most. Components should use semantic tokens, not primitives. That way, dark mode or a rebrand only needs the semantic layer to point at different primitives.

Component tokens

These are specific to one component: button-padding-x, input-border-color. They usually point to semantic tokens. You only need them when a component needs to differ from the general rule. Many small teams skip this layer and are fine.

A good test: if a token name could be used in two unrelated places, it is probably primitive. If it only makes sense in one role, it is semantic.

Naming that lasts

Names are the hardest part. A bad name is annoying for years.

A few rules we follow:

  • Name by purpose, not by value. color-danger still makes sense if danger becomes orange. color-red does not.
  • Use a clear order. A common pattern is category, then property, then role, then state: color-text-secondary, color-bg-hover. Pick one order and keep it.
  • Use scales with numbers for steps. space-1 to space-8, or font-size-sm, md, lg. Avoid names that cannot grow, like space-medium-large.
  • Keep the list short. If you have 400 tokens, people will not know which to pick. Start with what you use.
  • Write down the rule. One page that says how names are built. New people will follow it.

Do not name tokens after a brand or a feature ("checkout-blue"). Products change. The name outlives the reason.

From Figma variables to CSS

Figma has variables for colors, numbers, strings and booleans. They can hold modes, such as light and dark. This is where tokens live on the design side.

A workable setup:

  1. Create a primitives collection in Figma with your raw colors and sizes.
  2. Create a semantic collection with a light mode and a dark mode. Each token points to a primitive.
  3. Use only the semantic variables in components and screens.
  4. Export the variables to a JSON file, using a plugin or the Figma API.
  5. Turn the JSON into CSS custom properties, a Tailwind theme or whatever the code uses. A build tool such as Style Dictionary does this step.
  6. Keep the JSON in the code repository, so changes are reviewed like any other change.

The W3C Design Tokens Community Group is working on a shared file format, which you can read about at designtokens.org. It is still a draft, so check how stable it is before you build on it. A plain JSON file with your own simple structure also works well for a small team.

Whatever route you take, pick one source of truth. If Figma and the code both have their own copy, they will drift. We built a Figma plugin, UIX Design System, partly for this: it turns one brand color into a set of color scales, tokens and components you can export. You can find it in our Lab.

Themes and dark mode

This is where tokens pay off most.

With semantic tokens, a dark theme is a second set of values for the same names. In CSS it can be as small as this:

:root {
  --color-surface: #ffffff;
  --color-text-primary: #14161a;
}

[data-theme="dark"] {
  --color-surface: #14161a;
  --color-text-primary: #f2f3f5;
}

No component changes. The same .card reads --color-surface and gets the right color.

A few cautions. A dark theme is not just inverted colors. Shadows, borders and contrast need their own thought. Check text contrast in both modes against the WCAG guidelines. And do not forget images, charts and illustrations, which may need their own dark versions.

The same idea helps with white-label products. If each customer has a brand color, you change a few semantic tokens per account, not the whole interface.

What to do first in an existing product

You do not need to stop and rebuild everything. Here is a path that works in a live product:

  1. Audit what you have. Search the code for hex values and pixel sizes. You will likely find dozens of near-duplicate grays.
  2. Merge the duplicates. Choose one gray for borders, one for subtle text, and so on. Accept small visual shifts.
  3. Define a small semantic set. Text, surface, border, action, danger, success. Ten to twenty color tokens is a good start. Add spacing and radius.
  4. Replace values in the shared components first. Buttons, inputs, cards. These touch the most screens.
  5. Move the rest over time. Each time someone touches a screen, they swap raw values for tokens.
  6. Add a lint rule that warns when someone adds a raw hex color. It stops new drift.

The first pass takes days, not months, for a product of normal size. The value shows up the first time someone asks for a rebrand or a dark mode and you can say yes without dread.

Tokens are also the easiest part of a design to hand over exactly. We start a token set in every MVP design sprint, and keep it up to date when we work as a design partner on a live product.

If your team has a color problem or a theme problem and you are not sure where to start, send us a screen or two at /contact. We are happy to say what we would do first.

Want a second pair of eyes on your product?

Send your site or app and get a free design review from Rakib. No sales call, no cost.