Market
Pricing
Sign inStart
Field GuideCSS and web
CSS and web

Design tokens: one source of truth for colour and type

A brand colour that lives in forty files will drift. A token lives in one place and every platform reads from it. Here is how to structure design tokens, name them so they last, and ship them to code and design tools.

GradientlyVerified Gradiently account·October 1, 2026·5 min read
Cover: Topaz Temple · GR·N058·5B

The short version

  • Design tokens are named, platform neutral values for design decisions such as colours, font families, sizes, spacing, radii, shadows and motion timings.
  • Most token systems use three tiers: primitive tokens hold raw values, semantic tokens describe a purpose, and component tokens apply purposes to specific parts.
  • The W3C Design Tokens Community Group format stores tokens as JSON with $value and $type properties and references other tokens with curly braces.
  • Tools such as Style Dictionary transform one token file into CSS custom properties, JavaScript, iOS and Android resources.
  • Dark mode and multiple brands become a matter of swapping the values behind semantic tokens, while components stay unchanged.
On this page
What a design token looks likePrimitive, semantic and component tokensNaming design tokens so they lastFrom token file to CSS and appsDark mode and multiple brandsRolling out design tokens

Design tokens are named values for every design decision a brand repeats: colours, typefaces, type sizes, spacing, corner radii, shadows and animation timings. Instead of typing #5b21b6 into a stylesheet, a Figma file and an iOS app, you define color.brand.700 once, in one file, and generate each platform's format from it. Change the token and every product updates together. That single source of truth is the whole point.

What a design token looks like

A token has a name, a value and a type. The format published by the W3C Design Tokens Community Group writes them as JSON, with properties that start with a dollar sign so they cannot clash with group names.

json
{
  "color": {
    "violet": {
      "100": { "$type": "color", "$value": "#ede9fe" },
      "500": { "$type": "color", "$value": "#8b5cf6" },
      "700": { "$type": "color", "$value": "#6d28d9" },
      "900": { "$type": "color", "$value": "#4c1d95" }
    },
    "ink": { "$type": "color", "$value": "#14121f" },
    "paper": { "$type": "color", "$value": "#faf8ff" }
  },
  "font": {
    "heading": { "$type": "fontFamily", "$value": ["Fraunces", "Georgia", "serif"] },
    "body": { "$type": "fontFamily", "$value": ["Inter", "system-ui", "sans-serif"] }
  },
  "radius": {
    "control": { "$type": "dimension", "$value": { "value": 10, "unit": "px" } }
  },
  "duration": {
    "quick": { "$type": "duration", "$value": { "value": 160, "unit": "ms" } }
  }
}
Primitive tokens in the community group format. Groups nest freely; the path, such as color.violet.700, becomes the token's name.
The colour tokens above as swatches. These are raw ingredients: nothing yet says which one is a button or a heading.

Primitive, semantic and component tokens

A flat list of colours is a palette, not a system. The structure that holds up over years has three tiers, each referring to the one below. Components never touch raw values; they ask for a purpose.

Primitive

Example name

color.violet.700

Value

#6d28d9

Changes when

The palette is redesigned
Semanticcolor.action.primary

Value

{color.violet.700}

Changes when

A role moves to another colour
Semanticcolor.text.default

Value

{color.ink}

Changes when

Dark mode, a new brand
Component

Example name

button.primary.background

Value

{color.action.primary}

Changes when

One component needs an exception
TierExample nameValueChanges when
Primitivecolor.violet.700#6d28d9The palette is redesigned
Semanticcolor.action.primary{color.violet.700}A role moves to another colour
Semanticcolor.text.default{color.ink}Dark mode, a new brand
Componentbutton.primary.background{color.action.primary}One component needs an exception
References in curly braces are aliases. Change color.violet.700 and every token that points at it follows.
json
{
  "color": {
    "action": {
      "primary": { "$type": "color", "$value": "{color.violet.700}" },
      "primary-hover": { "$type": "color", "$value": "{color.violet.900}" }
    },
    "text": {
      "default": { "$type": "color", "$value": "{color.ink}" },
      "on-action": { "$type": "color", "$value": "{color.paper}" }
    },
    "surface": {
      "page": { "$type": "color", "$value": "{color.paper}" },
      "tint": { "$type": "color", "$value": "{color.violet.100}" }
    }
  }
}
Semantic tokens describe what a colour is for. This is the layer designers and engineers should talk in.

Many teams stop at two tiers, primitive and semantic, and add component tokens only where a component genuinely differs. That keeps the file small enough to understand.

Naming design tokens so they last

Names outlive values. A token called color.purple breaks the day the brand turns teal; a token called color.action.primary survives it. Name semantic tokens by role, and keep primitive names descriptive of the value.

Names that age badly

  • color.purple used for buttons
  • text.dark, which is light in dark mode
  • spacing.16 used as a layout rule
  • blue2, blueNew, blueFinal
  • hero.gradient.lisa named after a person

Names that last

  • color.action.primary
  • color.text.default
  • space.section pointing at {space.16}
  • A numbered scale such as blue.100 to blue.900
  • gradient.hero with its stops as tokens

Pick a pattern, such as category, then role, then variant, then state, and write it down in your brand style guide. Consistency in naming matters more than which pattern you choose.

From token file to CSS and apps

The token file is not shipped as it is. A build step transforms it into whatever each platform needs. Style Dictionary is the most widely used open source tool for this, and others read the same format. For the web, the output is usually CSS custom properties.

css
:root {
  --color-violet-100: #ede9fe;
  --color-violet-700: #6d28d9;
  --color-violet-900: #4c1d95;
  --color-ink: #14121f;
  --color-paper: #faf8ff;

  --color-action-primary: var(--color-violet-700);
  --color-text-default: var(--color-ink);
  --color-surface-page: var(--color-paper);

  --font-heading: Fraunces, Georgia, serif;
  --radius-control: 10px;
  --duration-quick: 160ms;
}

.button {
  background: var(--color-action-primary);
  color: var(--color-paper);
  border-radius: var(--radius-control);
  transition: background var(--duration-quick) ease;
}
Generated output. Aliases become var() references, so the semantic layer survives into the browser. See CSS variables for theming.

If you use Tailwind v4, the @theme block is itself a token layer: every --color-* variable becomes utilities. Tailwind colours shows how to wire a token ramp into it. The same file can also produce Swift constants and Android resources, which is where tokens pay for themselves on multi platform teams.

Dark mode and multiple brands

Because components only read semantic tokens, a theme is just a different set of values for that layer. Dark mode redefines color.text.default and color.surface.page; a second brand redefines color.action.primary. Nothing in the components changes.

css
@media (prefers-color-scheme: dark) {
  :root {
    --color-text-default: #e9e5f5;
    --color-surface-page: #0b0a14;
    --color-action-primary: var(--color-violet-500);
  }
}

[data-brand="harbour"] {
  --color-action-primary: #0f766e;
}
Two overrides, no component edits. Gradients deserve their own dark values too; dark mode gradients explains how to tune them.

Tokens in design tools

Figma Variables support collections and modes, which map neatly onto primitive and semantic tokens and light and dark themes. Keep the token file as the source and sync into the design tool, not the other way round, or the two will disagree within a month.

Rolling out design tokens

  1. 1

    Audit what exists

    Collect every colour, font size and spacing value in use. Expect duplicates that differ by one hex digit.

  2. 2

    Define primitives

    Reduce them to clear scales. Building colour ramps in OKLCH keeps steps even; see OKLCH explained.

  3. 3

    Add the semantic layer

    Name roles: text, surface, border, action, feedback. Point each at a primitive.

  4. 4

    Automate the build

    Generate CSS and app resources from the file in your build, never by hand.

  5. 5

    Guard it

    Lint for raw hex values in components, so new code uses tokens from day one.

Tokens keep the product consistent, but brands also drift in the graphics made outside it: posts, slides, banners. A Gradiently brand kit holds the same decisions, your colour palettes, heading and body fonts, logos and voice, so designs made in the Studio match. And because Gradiently works inside ChatGPT, Claude and other assistants that support remote MCP servers, an assistant with a scoped API key can create on brand designs from the same workspace. Brand consistency covers the wider habit.

Connect your AI assistant

Let Claude or any MCP client search Marks and make designs that open in the Studio.

Read the developer docs

Questions people ask

What are design tokens?

Named values for design decisions such as colours, fonts, spacing, radii and motion, stored in one platform neutral file and transformed into CSS, app code and design tool variables.

What is the difference between primitive and semantic tokens?

Primitive tokens hold raw values, like color.violet.700. Semantic tokens describe a purpose, like color.action.primary, and point at a primitive.

Are design tokens the same as CSS variables?

No. Tokens are the source, stored in a neutral format such as JSON; CSS custom properties are one output generated from them, alongside outputs for other platforms.

Is there a standard format for design tokens?

The W3C Design Tokens Community Group publishes a JSON format using $value, $type and curly brace aliases, which tools such as Style Dictionary can read.

How do design tokens handle dark mode?

Components read semantic tokens, and a dark theme supplies different values for those tokens, so components need no changes.

Share this guide

Written by GradientlyVerified Gradiently account

The team behind Gradiently, a design tool built around Marks: living gradients that make everything you design look like yours.

See our profile

On this page

What a design token looks likePrimitive, semantic and component tokensNaming design tokens so they lastFrom token file to CSS and appsDark mode and multiple brandsRolling out design tokens

Share this guide

Next in CSS and web

CSS linear gradient: the complete guide to linear-gradient()

Keep reading

All CSS and web guides
CSS and web

Build a CSS variables theme: light, dark and brand colours

5 min read

Themes go wrong when colours are named for what they look like instead of what they do. Name the roles, point them at a palette, and light mode, dark mode and a second brand become a few lines each.

CSS and web

Tailwind colours: using and extending the palette

5 min read

The default palette is a good starting point and a poor finishing one, because thousands of sites share it. Here is how Tailwind colours work in v4, and how to add your own without breaking anything.

Branding

How to make a brand style guide people actually use

5 min read

Most style guides are opened once and forgotten. The ones that work are short, show every rule, and live where people design. Here is how to write one of those.

Find the look that’s only yours.

Every Mark is a living background with one owner. Try an unclaimed Mark, and claim yours when it feels right.

Start designing

Check a certificate

Type a certificate number or a Mark’s code to see who owns it.

Works with ChatGPT and Claude

Ask your AI for a design. It makes it in your Mark, ready to edit.

ChatGPTClaude
How to connect

Product

  • Market
  • Explore
  • Pricing
  • Certificates

Learn

  • Field Guide
  • Help centre
  • What’s new

Developers

  • Overview
  • ChatGPT and Claude
  • API reference
  • API keys

Company

  • About
  • Contact us
  • Sign in

Legal

  • Terms
  • Privacy
  • Refunds
  • Mark protection
  • Cookies
  • All policies
Move through the letters. Each one wears a real Mark.Touch a letter to see its Mark.One name. Ten Marks inside it.
© 2026 Gradiently