Updated June 9, 2026 12 min read

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

Complete 2026 guide to Figma design tokens: Variables, primitives, semantic aliases, dark mode, DTCG export, and CSS/TypeScript handoff for UI teams.

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

Figma design tokens are named, platform-agnostic slots for visual decisions - implemented natively as Variables - that decouple a token’s name from its value so a single collection update propagates instantly across every component. Switching to dark mode or applying a rebrand means editing values in one place, not hunting hex codes across hundreds of layers. This guide covers the full workflow: primitive vs. semantic layers, collections, modes, naming, scopes, code export, and the DTCG standard.

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?

Design tokens 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 being standardized by the W3C Design Tokens Community Group (DTCG) so tools and codebases can exchange token files without custom parsers. 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.

Token indirection makes dark mode, density options, and rebrands manageable without rebuilding components. Update the value behind a token and every component that references it follows automatically.

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

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. Keep the two layers distinct and every future theme change stays confined to the semantic collection.

The semantic layer was absent in the majority of real Figma libraries reviewed while building Atomize. Most had a Primitives collection - raw palette steps - but components were wired directly to those Primitives. A button fill referencing blue/600 instead of interactive/default looks identical in light mode but breaks the moment you try to add a second theme: every component needs a manual override 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.

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

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.

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

Figma Variables are the native token engine - four types (Color, Number, String, Boolean) grouped into collections, each supporting multiple modes for parallel value sets. 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.

How to Set Up 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. 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. Structure your tokens as if they will leave Figma - because eventually they will.

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.
Variables for anything that needs theming, aliasing, or multi-mode values. 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.
A structured file (JSON, CSS custom properties, or TypeScript constants) with stable names that match the Variable paths in Figma, plus a short doc for any platform-specific exceptions. Atomize generates that artifact automatically from your Variables.
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.
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