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
| Tier | Also called | Purpose | Example |
|---|---|---|---|
| Primitive | Global / Core | Raw palette of all available values | --blue-500: #2563eb |
| Semantic | Alias / Role | Maps primitives to meaning | --color-primary: var(--blue-500) |
| Component | Scoped | Component-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
| Category | Examples | Notes |
|---|---|---|
| Color | Background, text, border, brand colors | Primitives + light/dark semantic variants |
| Spacing | Padding, margin, gap | Usually a scale (4px, 8px, 12px, 16px, 24px, 32px, 48px, 64px) |
| Typography | Font family, size, weight, line-height | Scale with ratio or explicit steps |
| Border radius | Small, medium, large, full (pill) | Consistent rounding |
| Shadow | Elevation levels (sm, md, lg, xl) | Often mapped to depth/elevation |
| Breakpoints | sm, md, lg, xl | Viewport width thresholds |
| Motion | Duration, easing curves | Animation timing tokens |
| Z-index | Layers (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
| Token | Value | Use |
|---|---|---|
--space-1 | 0.25rem (4px) | Tiny gaps (icon-to-text) |
--space-2 | 0.5rem (8px) | Compact padding |
--space-3 | 0.75rem (12px) | Input padding |
--space-4 | 1rem (16px) | Default padding/gap |
--space-6 | 1.5rem (24px) | Section padding |
--space-8 | 2rem (32px) | Large section spacing |
--space-12 | 3rem (48px) | Page section gaps |
--space-16 | 4rem (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
| Token | Light | Dark |
|---|---|---|
--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
| Convention | Example | Notes |
|---|---|---|
| Category-property-variant | color-primary-hover | Most common |
| Kebab-case | --color-bg-surface | CSS standard |
| Numeric scales | --space-4, --text-lg | T-shirt or numeric sizing |
Be consistent — mixing naming styles in the same project causes confusion.
9. Key takeaways
- Tokens = named design decisions: colors, spacing, typography, radii, shadows.
- Three tiers: primitive → semantic → component — update at the right level.
- Single source of truth — one JSON file can generate CSS, iOS, Android outputs.
- Theming = swapping the semantic layer while components stay unchanged.
- Spacing systems (4px/8px base) create visual rhythm and constrain choices.
- Color systems need contrast checking — tokens must produce accessible combinations.
Explain-It Challenge
Explain without notes:
- The three token tiers (primitive, semantic, component) and why the separation matters.
- How a spacing scale prevents the "200 different padding values" problem.
- Why tokens are described as platform-agnostic — what does that mean in practice?
Navigation: ← 1.6.h — Design Systems · ← 1.6 Overview