Starter Core concepts Design Tokens

Core concept 02

Design Tokens

A three-tier hierarchy that separates what a value is from what it means from where it's used. Change once, update everywhere.

The three tiers

The core problem tokens solve is the difference between a colour and its purpose. #d97706 is an amber colour. --accent-default is "the primary accent colour in this system." Those are different things, and conflating them causes maintenance pain.

T1
Primitives
Never used in components
--color-amber-500: #d97706; --color-gray-950: #141414; --space-4: 1rem;
T2
Semantic
Always use in components
--accent-default: var(--color-amber-500); --text-primary: var(--color-gray-950); --surface-raised: var(--color-white);
T3
Component
Scoped to their element
.card { --card-padding: var(--space-6); --card-radius: var(--radius-lg); }

Token naming

Tokens should describe purpose, not appearance. When a token's name describes what it looks like rather than what it does, renaming or retheming it becomes impossible without touching every reference.

✗ Appearance-named — breaks on theme change
--blue: #3b82f6; --white: #ffffff; --dark-gray: #1c1c1c;
✓ Purpose-named — survives any theme
--interactive-default: var(--color-blue-500); --surface-raised: var(--color-white); --surface-sunken: var(--color-gray-900);

Naming convention

Semantic tokens follow a [category]-[concept]-[variant]-[state] pattern. Categories group related tokens and make the namespace scannable.

CategoryExamplesCovers
--surface-*--surface-page, --surface-raisedBackground colours by elevation
--text-*--text-primary, --text-tertiaryText colours by visual weight
--border-*--border-subtle, --border-defaultBorder colours by prominence
--accent-*--accent-default, --accent-subtleBrand / accent colour roles
--interactive-*--interactive-default, --interactive-hoverInteractive element colours
--shadow-*--shadow-sm, --shadow-lgElevation shadows

Figma Variables connection

If your Figma Variable names mirror your CSS custom property names, there is zero translation cost between design and code. A Figma variable named color/surface/raised maps directly to --surface-raised in CSS.

High-leverage naming parity

When Figma Variable collections match CSS @layer tokens — light collection maps to :root, dark collection maps to [data-theme="dark"] — exporting tokens to CSS becomes a mechanical transform with no human interpretation required.

Figma → Style Dictionary → CSS pipeline
/* Figma Variables export (JSON) */
{
  "color/surface/raised": { "value": "#ffffff" },
  "color/accent/default": { "value": "#d97706" }
}

/* Style Dictionary transforms to CSS */
@layer tokens {
  :root {
    --surface-raised: #ffffff;
    --accent-default: #d97706;
  }
}

Live token values

These swatches show the current resolved value of each semantic token. Toggle the theme to watch them update — the swatch backgrounds are set as background-color: var(--token-name) and the browser resolves them live.

Live token swatches — toggle dark mode to see them change

TokenDescription

Token reference

Space

Based on a 4px grid. Use these instead of arbitrary values.

TokenValuepx
--space-10.25rem4px
--space-20.5rem8px
--space-30.75rem12px
--space-41rem16px
--space-51.25rem20px
--space-61.5rem24px
--space-82rem32px
--space-102.5rem40px
--space-123rem48px
--space-164rem64px
--space-205rem80px
--space-246rem96px
--space-328rem128px

Typography scale

Major Third ratio (1.25×). Use clamp() for responsive headings.

TokenValue~px
--size-3xs0.512rem~8px
--size-2xs0.64rem~10px
--size-xs0.8rem~13px
--size-sm1rem16px — body
--size-md1.25rem20px
--size-lg1.563rem25px
--size-xl1.953rem31px
--size-2xl2.441rem39px
--size-3xl3.052rem49px
--size-4xl3.815rem61px
--size-5xl4.768rem76px

Font families

TokenValueUse for
--font-serifInstrument Serif, GeorgiaHeadings, display text, blockquotes
--font-sansOutfit, system-uiBody text, UI labels, metadata
--font-monoJetBrains Mono, Fira CodeCode, technical content, labels