Episode 1 — Fundamentals / 1.6 — CSS Core Fundamentals

1.6.i — Design Tokens

In one sentence: Design tokens are the atomic, platform-agnostic values (colors, spacing, typography, radii, shadows) that encode design decisions once and distribute them to any platform — web CSS, mobile, email — through automated transformation.

Navigation: ← 1.6.h — Design Systems · ← 1.6 Overview


1. What are design tokens?

Design tokens are named design decisions stored in a structured format:

{
  "color": {
    "primary": { "value": "#2563eb", "type": "color" },
    "danger":  { "value": "#dc2626", "type": "color" }
  },
  "spacing": {
    "sm": { "value": "0.5rem", "type": "dimension" },
    "md": { "value": "1rem",   "type": "dimension" },
    "lg": { "value": "2rem",   "type": "dimension" }
  },
  "radius": {
    "sm": { "value": "0.25rem", "type": "dimension" },
    "md": { "value": "0.5rem",  "type": "dimension" }
  }
}

They are the single source of truth between design tools (Figma) and code platforms (CSS, iOS, Android).


2. Token tiers

TierAlso calledPurposeExample
PrimitiveGlobal / CoreRaw palette of all available values--blue-500: #2563eb
SemanticAlias / RoleMaps primitives to meaning--color-primary: var(--blue-500)
ComponentScopedComponent-specific binding--button-bg: var(--color-primary)

Why three tiers?

Primitive:  --blue-500: #2563eb      ← "this blue exists"
Semantic:   --color-primary: --blue-500   ← "primary means this blue"
Component:  --button-bg: --color-primary  ← "buttons use the primary color"

Brand change: update the semantic mapping (--color-primary: --green-600) — every component updates. Component variation: override just the component token (.button-danger { --button-bg: var(--color-danger); }).


3. Token categories

CategoryExamplesNotes
ColorBackground, text, border, brand colorsPrimitives + light/dark semantic variants
SpacingPadding, margin, gapUsually a scale (4px, 8px, 12px, 16px, 24px, 32px, 48px, 64px)
TypographyFont family, size, weight, line-heightScale with ratio or explicit steps
Border radiusSmall, medium, large, full (pill)Consistent rounding
ShadowElevation levels (sm, md, lg, xl)Often mapped to depth/elevation
Breakpointssm, md, lg, xlViewport width thresholds
MotionDuration, easing curvesAnimation timing tokens
Z-indexLayers (dropdown, modal, toast)Prevent z-index wars with named layers

4. From tokens to CSS

Manual approach (simple projects)

Define tokens directly as CSS custom properties:

:root {
  /* Primitives */
  --blue-50: #eff6ff;
  --blue-500: #2563eb;
  --blue-700: #1d4ed8;
  --red-500: #ef4444;

  /* Semantic */
  --color-primary: var(--blue-500);
  --color-primary-hover: var(--blue-700);
  --color-danger: var(--red-500);
  --color-bg: #ffffff;
  --color-text: #1a1a2e;

  /* Spacing */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-4: 1rem;
  --space-8: 2rem;

  /* Radius */
  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 1rem;
  --radius-full: 9999px;
}

Automated approach (larger teams)

Tools like Style Dictionary or Tokens Studio transform a central JSON token file into platform-specific outputs:

tokens.json  →  CSS custom properties
             →  Sass variables
             →  iOS Swift constants
             →  Android XML resources
             →  Tailwind config values

One update, all platforms sync — this is the real power of tokens at scale.


5. Tokens and theming

Tokens make theming a mapping exercise, not a rewrite:

/* Default (light) */
:root {
  --color-bg: var(--white);
  --color-text: var(--gray-900);
  --color-surface: var(--gray-100);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
}

/* Dark theme — override semantic layer only */
[data-theme="dark"] {
  --color-bg: var(--gray-900);
  --color-text: var(--gray-100);
  --color-surface: var(--gray-800);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}

Components that use var(--color-bg) automatically adapt — zero component CSS changes.


6. Spacing systems

The 4px / 8px base

Most design systems use a 4px or 8px base unit:

4px → 8px → 12px → 16px → 24px → 32px → 48px → 64px
TokenValueUse
--space-10.25rem (4px)Tiny gaps (icon-to-text)
--space-20.5rem (8px)Compact padding
--space-30.75rem (12px)Input padding
--space-41rem (16px)Default padding/gap
--space-61.5rem (24px)Section padding
--space-82rem (32px)Large section spacing
--space-123rem (48px)Page section gaps
--space-164rem (64px)Hero section padding

Why not arbitrary values? Constrained spacing creates visual rhythm — elements align, white space feels intentional, and the codebase is auditable.


7. Color systems

Primitive palette

Generate a full shade scale (50–950) for each hue:

blue-50  blue-100  blue-200  blue-300  blue-400  blue-500  blue-600  blue-700  blue-800  blue-900  blue-950

Semantic mapping

TokenLightDark
--color-bg--white--gray-900
--color-text--gray-900--gray-100
--color-primary--blue-500--blue-400
--color-danger--red-600--red-400
--color-border--gray-200--gray-700

Contrast considerations

Color tokens must meet WCAG contrast ratios:

  • 4.5:1 for normal text
  • 3:1 for large text (≥18pt or ≥14pt bold)

Test all semantic color pairs (--color-text on --color-bg, --color-primary on --color-bg, etc.).


8. Token naming conventions

ConventionExampleNotes
Category-property-variantcolor-primary-hoverMost common
Kebab-case--color-bg-surfaceCSS standard
Numeric scales--space-4, --text-lgT-shirt or numeric sizing

Be consistent — mixing naming styles in the same project causes confusion.


9. Key takeaways

  1. Tokens = named design decisions: colors, spacing, typography, radii, shadows.
  2. Three tiers: primitive → semantic → component — update at the right level.
  3. Single source of truth — one JSON file can generate CSS, iOS, Android outputs.
  4. Theming = swapping the semantic layer while components stay unchanged.
  5. Spacing systems (4px/8px base) create visual rhythm and constrain choices.
  6. Color systems need contrast checking — tokens must produce accessible combinations.

Explain-It Challenge

Explain without notes:

  1. The three token tiers (primitive, semantic, component) and why the separation matters.
  2. How a spacing scale prevents the "200 different padding values" problem.
  3. Why tokens are described as platform-agnostic — what does that mean in practice?

Navigation: ← 1.6.h — Design Systems · ← 1.6 Overview