Updated July 27, 2026 12 min read
Junior Foundations

Figma Design Tokens: The Complete Guide for UI/UX Designers

The 2026 guide to Figma design tokens: Variables setup, semantic aliases, dark mode theming, DTCG export, and automated CSS/TypeScript sync.

Figma Design Tokens: The Complete Guide for UI/UX Designers

Design tokens in Figma turn your colors, spacing, and typography into a single source of truth — Variables that propagate across every component and export directly to code. That indirection means a single collection update applies instantly everywhere: dark mode, rebrand, or density tweak, no hunting hex codes across hundreds of layers. This design tokens guide covers the full workflow: primitive vs. semantic layers, collections, modes, naming, scopes, code export, and the DTCG standard. If you are looking for a hands-on design tokens Figma tutorial, the step-by-step section below walks through creating and connecting every layer for a production-ready token system.

Related workflows: Figma vs Pencil for tooling choices, Figma MCP for AI in Dev Mode, WCAG contrast audits at library scale, and dark mode with Variables.

What Are Figma Design Tokens?

So what are design tokens? They are the shared contract between design and code — a named decision that both sides reference instead of raw values. The concept was popularized by the Salesforce Lightning Design System team and is now standardized by the W3C Design Tokens Community Group (DTCG) so tools and codebases can exchange token files without custom parsers. The DTCG specification traces the evolution from proprietary formats to an interoperable standard that any tool and codebase can consume. In Figma, tokens live as Variables: a named slot holds the value, and every component that references it updates the moment the value changes. That indirection is what makes dark mode, density options, and rebrands manageable at scale. For accessibility-driven token choices - such as ensuring contrast ratios between semantic pairs - the WCAG 2.1 contrast guidelines define the thresholds your color tokens must satisfy.

Figma Variables vs Design Tokens: What’s the Difference?

Design tokens are the concept - a named decision (a color, a spacing value, a font size) that both design and code reference instead of a raw value. Figma Variables are the native mechanism that implements that concept inside Figma: a typed slot (Color, Number, String, or Boolean) that holds values and supports aliases and modes. Every Figma Variable you create is effectively a design token; the distinction matters when connecting Figma to a build pipeline, because not every token workflow requires Figma Variables - some teams maintain token files in JSON outside Figma entirely. Within a Figma-first workflow, the two terms are used interchangeably in practice.

Primitive vs Semantic Tokens

Design tokenization starts with a simple principle: every production-grade token system needs two layers - primitives and semantics - or the first theme request breaks everything. Primitives hold raw values with no product meaning (palette steps, spacing increments, type sizes); semantics alias them by UI role (page background, primary action, destructive text). Without that separation, components bind directly to raw values, and adding a second theme means manually overriding each one. When building Atomize, Vitalina reviewed hundreds of Figma libraries and found most had primitives but no semantic layer - buttons were wired to blue/600 instead of interactive/default, so dark mode required component-level surgery rather than a mode switch. The two-layer architecture feels like extra work upfront; it pays back immediately the first time someone asks for a dark mode toggle. Keep the two layers distinct and every future theme change stays confined to the semantic collection.

Two-layer token architecture: Primitive tokens holding raw values flow into Semantic tokens which resolve differently in Light and Dark modes, then bind to Components
Layer 1 holds raw values (primitives). Layer 2 aliases them by UI role (semantics). Components only bind to Layer 2 - so a mode switch updates everything automatically.

Color

When setting up Figma colors as tokens, primitives hold raw palette steps with no product meaning. Semantics alias them by UI role. A button fill references interactive/default, never a hex - so dark mode is just a mode switch on the semantic collection with zero component changes.

/* Primitives */
gray/50   →  #f9fafb
gray/950  →  #030712
blue/600  →  #2563eb
red/600   →  #dc2626

/* Semantic - Light mode */
background/default       →  gray/50 (#f9fafb)
text/primary             →  gray/950 (#030712)
text/subdued             →  gray/600 (#4b5563)
interactive/default      →  blue/600 (#2563eb)
interactive/destructive  →  red/600 (#dc2626)

/* Semantic - Dark mode (same names, different values) */
background/default       →  gray/950 (#030712)
text/primary             →  gray/50 (#f9fafb)

Typography

Primitive type sizes: font/size/12, font/size/14, font/size/16, font/size/20, font/size/24, font/size/32. Semantic presets: text/body/sm uses font/size/12, weight/regular, lineheight/150%; text/body/md uses font/size/14; text/heading/lg uses font/size/24, weight/semibold, lineheight/110%. Presets bundle primitives so your product uses a controlled subset of the full scale.

Primitive vs semantic: at a glance

PropertyPrimitive tokenSemantic tokenHas modes?
Page backgroundgray/50 (#f9fafb)background/defaultYes — light: gray/50, dark: gray/950
Primary textgray/950 (#030712)text/primaryYes — light: gray/950, dark: gray/50
Muted textgray/600 (#4b5563)text/subduedYes — light: gray/600, dark: gray/400
Primary button fillblue/600 (#2563eb)interactive/defaultYes — light: blue/600, dark: blue/400
Destructive actionred/600 (#dc2626)interactive/destructiveYes — light: red/600, dark: red/400
Section gapspace/6 (24px)layout/section-gapNo — spacing rarely needs theming
Card corner radiusradius/md (8px)component/card-radiusNo — shape stays constant across modes

Spacing, radius, elevation, motion

Spacing, radius, and motion use Number variables so auto-layout padding, gap, corner radius, and effect fields stay on-scale automatically.

/* Spacing - Number variables, base-4 scale */
space/1= 4px
space/2= 8px
space/3= 12px
space/4= 16px
space/6= 24px
space/8= 32px
space/12= 48px
space/16= 64px

/* Radius */
radius/none= 0
radius/sm= 4px
radius/md= 8px
radius/lg= 12px
radius/full= 9999px

/* Motion duration */
duration/fast= 150ms
duration/base= 250ms
duration/slow= 400ms

Figma Variables as Your Token Engine

How do design tokens work in Figma? Under the hood, Figma Variables are the native token engine - four types (Color, Number, String, Boolean) grouped into collections, each supporting multiple modes for parallel value sets. To understand how to use design tokens in Figma effectively, think of Variables as the storage layer: you create them once, alias them into semantic groups, and bind every component property to a Variable rather than a raw value. Most teams underuse this: they create color variables but leave spacing and radius as raw numbers, so auto-layout stays off-scale and padding drifts between designers. Atomize users who fully populate Number collections for space, radius, and motion see component reviews drop from hours to minutes because every value traces back to a named token. Alias primitives into semantics using the variable picker (the cube icon) so the relationship is explicit, navigable, and enforced inside the file.

Minimal collection setup

  1. Create “Primitives - Color”: raw palette steps, no modes. Restrict editing to system owners.
  2. Create “Semantic - Color”: variables aliased to primitives. Add Light and Dark modes; set values per mode.
  3. Create “Primitives - Space”: Number variables for your spacing scale.
  4. Create “Primitives - Radius” and “Primitives - Motion” as Number variables.
  5. On each component, bind fills, strokes, padding, gap, corner radius, and text to Variables - never to raw values.

Modes: theming without duplicate components

Modes live on a collection and define parallel value sets. The Semantic - Color collection has Light and Dark modes; every semantic variable gets two values. Apply mode at frame level to preview the whole flow in dark theme without touching a single component. Add modes only when the whole collection needs parallel values; unrelated axes (color themes vs. density) belong on separate collections.

Scopes: where a variable is allowed

Scopes control which design properties a variable appears in. A text color variable scoped to “Text fill” will not show up in the stroke picker. A spacing variable scoped to “Gap” and “Padding” will not appear in corner radius. Tight scopes prevent accidental misapplication and reduce picker noise as the library grows.

Variables vs Styles: when to use which

Use caseUse VariablesUse StylesWhy
Dark mode / themingYesNoModes on semantic collections switch values in one click; Styles need per-theme duplicates
Spacing & radius valuesYesNoNumber Variables feed auto-layout math; Styles do not hold numeric tokens
Brand color paletteYesLimitedAliases let semantics reference primitives; Styles store static hex values
One-off text presetsNoYesA single heading style with a specific font stack does not benefit from variable indirection
Effects & shadowsLimitedYesEffects (drop shadows, blurs) are not yet fully tokenizable via Variables in Figma
Prototype interactionsYesNoString/Boolean Variables drive variant swaps; Styles cannot control interactivity

How to Create Design Tokens in Figma: Step by Step

  1. Create a Primitives - Color collection: raw palette steps (gray/50 through gray/950, blue/600, red/600). No modes, no aliases - just values. Restrict edit access to system owners.
  2. Create a Semantic - Color collection: add Light and Dark modes. Alias each semantic variable to a primitive using the cube icon in the value picker - never enter hex values directly.
  3. Create Primitives - Space and Primitives - Radius collections using Number variables. Set your spacing scale (4, 8, 12, 16, 24, 32, 48, 64) and radius steps (0, 4, 8, 12, 9999).
  4. Bind every component: fills and strokes to Semantic - Color variables, padding and gap to Primitives - Space, corner radius to Primitives - Radius. Never bind a component directly to a Primitive - Color variable.
  5. Set up export: use Atomize or right-click a collection → Export to JSON to generate CSS custom properties, TypeScript constants, or DTCG JSON. Add this step to your library publish checklist so token files stay current with every release.

Naming Tokens

Token names are the public API shared by designers and developers - bad names create drift that silently breaks theming. The constraint is that semantic names must stay meaningful across every mode: text/gray is wrong because it stops making sense the moment you add a dark theme; text/subdued is correct because it describes intent, not a hue. The category/role/variant pattern (color/text/primary, spacing/gap/md) maps directly to CSS custom property conventions (--color-text-primary), so Figma paths and code names stay in sync with no translation layer. Agree on casing and naming conventions once, document them in variable descriptions, and enforce them in library reviews.

The most common bad naming pattern Atomize flags in audits is hue-encoded semantic names: text/blue, border/gray-300, background/white. These pass review in light mode because the name and the resolved value happen to agree. They break silently the moment a dark mode value is assigned - the variable still exists and resolves to something, but the name now lies about what it points to. The first time an engineer opens browser devtools and sees --text-blue resolving to near-white, engineering trust in the token system is damaged. Rename with a deprecation window, document the role-based replacement in the variable description, and remove the old name on the next major version.

Exporting Tokens to Code

Tokens only become a shared contract when the same names ship in the codebase - a token that exists only in Figma is a private note. For teams wondering how to export design tokens from Figma, the answer depends on whether you need a manual DTCG JSON dump or an automated pipeline. Tools like Token Studio or Atomize bridge the gap: without a sync pipeline, design updates and code values drift apart silently: engineers hard-code hex values because they can’t reliably read the Figma file, and the token system becomes decorative. Atomize reads your Figma Variables directly and exports structured token files - JSON, CSS custom properties, or TypeScript constants - so the repository always reflects the current library state without manual copy-paste. Connect the pipeline once and every library publish becomes a code update.

A typical CSS export from a semantic color collection. In dark mode the same variable names resolve to different values - the app switches themes by toggling a data attribute, not loading a second stylesheet.

/* Semantic color tokens - Light mode */
--color-background-default:     #f9fafb;
--color-text-primary:           #111827;
--color-text-subdued:           #4b5563;
--color-interactive-default:    #2563eb;
--color-interactive-destructive: #dc2626;

/* Dark mode: toggled via [data-theme="dark"] on <html> */
[data-theme="dark"] {
  --color-background-default:   #030712;
  --color-text-primary:         #f9fafb;
  --color-text-subdued:         #9ca3af;
  --color-interactive-default:  #3b82f6;
}

A token only in Figma is a private note. A token in Figma and in the build pipeline is a shared contract.

Token export formats compared

FormatBest forTool supportKey limitation
CSS custom propertiesWeb projects, all modern browsersAtomize, Style Dictionary, all major toolsNo token type metadata; does not compile for native platforms
DTCG JSONMulti-platform pipelines (web, iOS, Android)Style Dictionary, Theo, Token TransformerRequires clean $type on every token; strict structure
TypeScript constantsType-safe codebases, design token autocompleteAtomize, custom build scriptsBuild step required; not useful for CSS-only projects
SCSS variablesLegacy web projects, design-heavy stylesheetsMost export pluginsNo aliasing support; values duplicate rather than reference

Best Practices

  • Ship primitives before semantics; alias, never duplicate raw values in components.
  • Restrict edit access to primitive collections; day-to-day work happens on semantics.
  • Use variable descriptions for intent, contrast pairings, and deprecation notices.
  • Version token exports alongside library releases - same cadence, same changelog.
  • Tokenize recurring decisions; one-off edge cases do not need a token.
  • Audit annually: merge duplicates, delete unused tokens, document any breaking renames.

Common Pitfalls

  • Binding primitives directly on components - you lose the semantic indirection; theme switches require manual component edits.
  • Too many modes on one collection - split unrelated axes (color themes vs. density) into separate collections.
  • String variables for every number - use Number type for space and radius so auto-layout math stays consistent.
  • Hue words in semantic names (text/blue, background/white) - break when the palette changes.
  • No export pipeline - engineering invents parallel names; drift is guaranteed.

DTCG Interoperability

DTCG compliance future-proofs your token system against toolchain changes by establishing a portable, parser-agnostic JSON format. Most teams today use proprietary export schemas tied to a single plugin - when that plugin is deprecated or a new platform is added, the entire token file must be manually migrated. The W3C DTCG specification gives every token a $value and a $type (color, dimension, duration, shadow, etc.), and tools like Style Dictionary and Token Transformer read that format natively without custom parsers. Figma’s Variable export direction aligns with DTCG, so category/role/variant naming maps cleanly to the group hierarchy and survives toolchain swaps with no renaming. Material Design 3 uses a similar token architecture with source and blend color roles - studying their scheme helps teams validate their own semantic layer decisions. Structure your tokens as if they will leave Figma - because eventually they will.

{
  "color": {
    "text": {
      "primary": {
        "$value": "{color.gray.950}",
        "$type": "color",
        "$description": "Primary body copy and heading text color"
      }
    },
    "background": {
      "default": {
        "$value": "{color.gray.50}",
        "$type": "color",
        "$description": "Default page background"
      }
    }
  },
  "dimension": {
    "space": {
      "gap": {
        "md": {
          "$value": "8px",
          "$type": "dimension",
          "$description": "Default gap between inline elements"
        }
      }
    }
  }
}

Final verdict - Figma Design Tokens

Design tokens built on a two-layer architecture are the only foundation that scales - primitives hold raw values, semantics own product intent, and the gap between them is where dark mode, rebrands, and density variants live for free. The investment is front-loaded: getting the collections, naming, and export pipeline right in the first sprint means every future change is a value edit rather than a component surgery. Atomize users consistently report that the first full token export to CSS is the moment the design system stops being a Figma artifact and starts being a shared engineering asset. Build the structure early, treat the token file as source-of-truth, and the system pays compounding returns for the life of the product.

Variables are how you implement design tokens in Figma. "Design token" is the concept (a named value for a UI decision); Variables are the native mechanism - collections, aliases, modes - that replaces ad-hoc styles for systematic values.
Use Variables for decisions that require theming, aliasing, or multi-mode values - colors, spacing, and radii belong in Variables so a mode switch updates them everywhere at once. Styles remain useful for one-off text presets or effects, but a token-first system centralizes decisions in Variables and references them from Styles or components as needed.
Start with two per concern: primitives and semantics for color; same for space if the scale is non-trivial. Add collections when ownership, mode axes, or release cadence differ - not for every experiment.
Introduce semantic variables first and alias them to your existing color values. Rebind components one category at a time (fills before strokes before text). Publish migration notes; never rename tokens without a deprecation window.
The token export should deliver a structured file (JSON, CSS custom properties, or TypeScript constants) with stable names that match the Variable paths in Figma, plus a short README noting any platform-specific overrides. Atomize generates that artifact automatically from your Variables so the export is reproducible on every library publish.
Start with a Primitives - Color collection holding raw hex values, then create a Semantic - Color collection where every variable aliases a primitive using the cube icon. Add Number variables for spacing and radius in separate collections. Bind components to semantic variables only. See the step-by-step setup section above for the full sequence.
Design tokens are the concept - a named value that design and code share instead of raw hex or pixel values. Figma Variables are the native implementation of that concept inside Figma: typed slots (Color, Number, String, Boolean) that support aliases and modes. In practice the terms are used interchangeably when working in a Figma-first workflow.
Figma Variables are typed, reusable values (Color, Number, String, Boolean) that store design decisions such as colors, spacing, and radii. Unlike static styles, Variables support aliases — one variable can reference another — and modes for theming. Variables replace hardcoded values with a single source of truth that propagates across your file, so changing a color in one place updates every layer that references it.
Select a layer, then click the variable icon (hexagon) next to any supported property in the right sidebar — fill, stroke, text color, spacing, or corner radius. Choose the variable from the dropdown. You can also set a variable as the default for a property in a component variant, and use variable aliases to build semantic layers that reference primitive values. When you change the underlying variable value, every layer bound to it updates automatically.
Click the Variables tab in the left navigation bar — no need to deselect everything on the canvas first. From the Variables panel you can create collections, add variables, set modes (light/dark, brand themes), and manage aliases between variables across collections. The entry point was moved from the old right-sidebar section in a 2025 update; the dedicated left-nav tab is now the single access point.
Right-click any Variable collection and choose Export to JSON. This produces a DTCG-compatible file with your token names, values, types, and alias chains. For automated code generation, Atomize reads your Variables directly and produces CSS custom properties, SCSS variables, TypeScript constants, or Tailwind presets through a Style Dictionary pipeline — no manual export step required for each update.
Yes — Figma supports design tokens natively through its Variables system, introduced at Config 2023 and now the standard way to store and reuse design decisions across files. Variables cover Color, Number, String, and Boolean types with alias chaining and mode support. For teams that need JSON export, multi-platform code generation, or advanced token management, Figma-native plugins like Atomize and Tokens Studio extend the built-in capabilities.
Right-click any Variable collection and choose Export to JSON for a DTCG-aligned file, then run it through Style Dictionary to generate CSS custom properties. Atomize automates this end-to-end: it reads your Variable collections and writes a ready-to-import CSS file with correct mode separation for light and dark themes, no manual build step required.
See all

Follow us on every platform