Design Systems & Tokens
A complete guide to building scalable design systems with design tokens. Learn how to create, organize, and implement tokens across platforms for consistent, maintainable design.
Introduction
A design system is a collection of reusable components, guided by clear standards, that can be assembled to build applications. Design tokens are the foundational building blocks—the visual design atoms like colors, spacing, and typography that power your design system.
Why Design Systems Matter:
- Ensure consistency across products and platforms
- Speed up design and development workflows
- Create a shared language between design and engineering
- Make updates and rebranding easier
- Scale design across teams and products
What Are Design Tokens?
Design tokens are named entities that store visual design attributes. They're platform-agnostic—the same token can generate CSS variables, iOS Swift code, Android XML, and more.
// Token definition (JSON)
{
"color": {
"brand": {
"primary": {
"value": "#0066ff",
"type": "color",
"description": "Primary brand color"
}
}
}
}
/* Generated CSS */
:root {
--color-brand-primary: #0066ff;
}
/* Usage */
.button {
background: var(--color-brand-primary);
}
// Generated Swift (iOS)
struct ColorTokens {
static let colorBrandPrimary = UIColor(hex: "0066ff")
}
Token Categories
Design tokens are typically organized into categories based on their purpose.
Core Token Categories
| Category | Purpose | Examples |
|---|---|---|
| Color | Brand colors, UI colors, semantic colors | primary, secondary, success, error, background |
| Spacing | Margins, padding, gaps | xs, sm, md, lg, xl (0.5rem, 1rem, 2rem, etc.) |
| Typography | Font families, sizes, weights, line heights | font-family-sans, font-size-body, font-weight-bold |
| Sizing | Width, height, icon sizes | icon-sm, icon-md, button-height |
| Border | Border widths, styles, radius | border-width-thin, border-radius-sm |
| Shadow | Box shadows, elevation | shadow-sm, shadow-md, shadow-lg |
| Motion | Animation durations, easing | duration-fast, duration-normal, easing-standard |
| Z-index | Layering order | z-dropdown, z-modal, z-tooltip |
Naming Conventions
Consistent naming is critical for scalability. Use clear, descriptive names that convey meaning and hierarchy.
Common Naming Patterns
Category-Based Naming
/* Pattern: category-property-variant-state */
--color-background-primary
--color-background-secondary
--color-text-primary
--color-text-secondary
--spacing-sm
--spacing-md
--font-size-body
--font-size-heading
Scale-Based Naming
/* Numeric or t-shirt scales */
--space-1, --space-2, --space-3
--space-xs, --space-sm, --space-md, --space-lg, --space-xl
/* Color scales */
--gray-50, --gray-100, --gray-200, ... --gray-900
--blue-50, --blue-100, ... --blue-900
Semantic Naming
/* Purpose-driven names */
--color-primary
--color-success
--color-warning
--color-error
--button-primary-background
--button-primary-text
--input-border-default
--input-border-focus
Non-Descriptive Names
/* Too vague or specific */
--blue /* Which blue? */
--color1 /* Meaningless */
--big-spacing /* Imprecise */
--the-blue-on-homepage /* Too specific */
Naming Best Practices:
- Use consistent casing (kebab-case for CSS, camelCase for JavaScript)
- Start with the category for better grouping
- Use meaningful, not literal names (semantic vs. presentational)
- Include variants and states when applicable
- Avoid platform-specific or implementation details
Token Hierarchy
Design tokens typically exist in a three-tier hierarchy: Global → Alias → Component.
Level 1: Global Tokens (Primitives)
Raw values with no context. These are your palette.
Level 2: Alias Tokens (Semantic)
Context-aware names that reference global tokens.
Level 3: Component Tokens
Component-specific tokens that reference alias or global tokens.
/* Token hierarchy in practice */
/* Level 1: Global/Primitive tokens */
:root {
--blue-50: #eff6ff;
--blue-500: #3b82f6;
--blue-900: #1e3a8a;
--space-2: 0.5rem;
--space-4: 1rem;
}
/* Level 2: Alias/Semantic tokens */
:root {
--color-primary: var(--blue-500);
--color-text-primary: var(--blue-900);
--spacing-sm: var(--space-2);
--spacing-md: var(--space-4);
}
/* Level 3: Component tokens */
.button {
--button-bg: var(--color-primary);
--button-text: white;
--button-padding: var(--spacing-sm) var(--spacing-md);
background: var(--button-bg);
color: var(--button-text);
padding: var(--button-padding);
}
/* This creates a maintainable cascade:
component → semantic → primitive */
Why Use This Hierarchy?
- Flexibility: Change a semantic token and all components update
- Clarity: Each level has a clear purpose
- Maintainability: Updates happen at the right level
- Theming: Easy to create theme variants by swapping semantic tokens
Color Tokens
Color tokens are the most common design tokens. Organize them by palette, semantic meaning, and component usage.
Color Scales
Create color scales with consistent steps for flexibility and theming.
/* Color scale tokens */
:root {
/* Gray scale */
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-300: #d1d5db;
--gray-400: #9ca3af;
--gray-500: #6b7280;
--gray-600: #4b5563;
--gray-700: #374151;
--gray-800: #1f2937;
--gray-900: #111827;
/* Brand color scales */
--blue-500: #3b82f6;
--green-500: #10b981;
--red-500: #ef4444;
--yellow-500: #f59e0b;
}
Semantic Color Tokens
/* Map scales to semantic meanings */
:root {
/* Brand colors */
--color-primary: var(--blue-500);
--color-primary-hover: var(--blue-600);
--color-primary-light: var(--blue-100);
/* UI colors */
--color-background: var(--gray-50);
--color-surface: white;
--color-border: var(--gray-200);
/* Text colors */
--color-text-primary: var(--gray-900);
--color-text-secondary: var(--gray-600);
--color-text-tertiary: var(--gray-400);
/* Status colors */
--color-success: var(--green-500);
--color-warning: var(--yellow-500);
--color-error: var(--red-500);
--color-info: var(--blue-500);
}
Dark Mode Color Tokens
/* Light theme (default) */
:root {
--color-background: white;
--color-text: var(--gray-900);
--color-border: var(--gray-200);
}
/* Dark theme */
:root[data-theme="dark"],
.dark-mode {
--color-background: var(--gray-900);
--color-text: var(--gray-50);
--color-border: var(--gray-700);
}
/* Components automatically adapt */
.card {
background: var(--color-background);
color: var(--color-text);
border: 1px solid var(--color-border);
}
Spacing Tokens
Spacing tokens create rhythm and consistency in your layouts. Use a consistent scale.
Spacing Scale Example
Common Spacing Systems
/* Option 1: Numeric scale (4px base) */
:root {
--space-0: 0;
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.25rem; /* 20px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-10: 2.5rem; /* 40px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
--space-20: 5rem; /* 80px */
--space-24: 6rem; /* 96px */
}
/* Option 2: T-shirt sizes */
:root {
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 2rem;
--space-xl: 4rem;
--space-2xl: 8rem;
}
/* Option 3: Semantic names */
:root {
--spacing-tight: 0.5rem;
--spacing-normal: 1rem;
--spacing-relaxed: 1.5rem;
--spacing-loose: 2rem;
}
Using Spacing Tokens
/* In components */
.card {
padding: var(--space-4);
margin-bottom: var(--space-6);
gap: var(--space-3);
}
.button {
padding: var(--space-2) var(--space-4);
}
.section {
padding-top: var(--space-12);
padding-bottom: var(--space-12);
}
/* Spacing utilities */
.p-4 { padding: var(--space-4); }
.m-4 { margin: var(--space-4); }
.gap-4 { gap: var(--space-4); }
Typography Tokens
Typography tokens include font families, sizes, weights, line heights, and letter spacing.
Type Scale
/* Typography tokens */
:root {
/* Font families */
--font-family-sans: system-ui, -apple-system, sans-serif;
--font-family-serif: Georgia, Cambria, "Times New Roman", serif;
--font-family-mono: "SF Mono", Monaco, "Cascadia Code", monospace;
/* Font sizes */
--font-size-xs: 0.75rem; /* 12px */
--font-size-sm: 0.875rem; /* 14px */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.125rem; /* 18px */
--font-size-xl: 1.25rem; /* 20px */
--font-size-2xl: 1.5rem; /* 24px */
--font-size-3xl: 2rem; /* 32px */
--font-size-4xl: 2.5rem; /* 40px */
--font-size-5xl: 3rem; /* 48px */
/* Font weights */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* Line heights */
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
/* Letter spacing */
--letter-spacing-tight: -0.025em;
--letter-spacing-normal: 0;
--letter-spacing-wide: 0.025em;
}
Semantic Typography Tokens
/* Map to semantic uses */
:root {
/* Body text */
--text-body-font: var(--font-family-sans);
--text-body-size: var(--font-size-base);
--text-body-weight: var(--font-weight-normal);
--text-body-line-height: var(--line-height-normal);
/* Headings */
--text-heading-font: var(--font-family-sans);
--text-heading-weight: var(--font-weight-bold);
--text-heading-line-height: var(--line-height-tight);
--text-h1-size: var(--font-size-4xl);
--text-h2-size: var(--font-size-3xl);
--text-h3-size: var(--font-size-2xl);
--text-h4-size: var(--font-size-xl);
/* Code */
--text-code-font: var(--font-family-mono);
--text-code-size: 0.875em;
}
/* Apply to elements */
body {
font-family: var(--text-body-font);
font-size: var(--text-body-size);
font-weight: var(--text-body-weight);
line-height: var(--text-body-line-height);
}
h1, h2, h3, h4 {
font-family: var(--text-heading-font);
font-weight: var(--text-heading-weight);
line-height: var(--text-heading-line-height);
}
h1 { font-size: var(--text-h1-size); }
h2 { font-size: var(--text-h2-size); }
h3 { font-size: var(--text-h3-size); }
h4 { font-size: var(--text-h4-size); }
code {
font-family: var(--text-code-font);
font-size: var(--text-code-size);
}
Implementation
Design tokens can be implemented in various ways depending on your tech stack and workflow.
CSS Variables (Web)
/* tokens.css */
:root {
/* Colors */
--color-primary: #0066ff;
--color-text: #1a1a1a;
/* Spacing */
--space-4: 1rem;
/* Typography */
--font-size-base: 1rem;
}
/* Use in components */
.button {
background: var(--color-primary);
padding: var(--space-4);
font-size: var(--font-size-base);
}
Sass/SCSS Variables
// _tokens.scss
$color-primary: #0066ff;
$color-text: #1a1a1a;
$space-4: 1rem;
$font-size-base: 1rem;
// Use in components
.button {
background: $color-primary;
padding: $space-4;
font-size: $font-size-base;
}
JavaScript/TypeScript
// tokens.js
export const tokens = {
color: {
primary: '#0066ff',
text: '#1a1a1a'
},
spacing: {
'4': '1rem'
},
fontSize: {
base: '1rem'
}
};
// Use in styled-components
import styled from 'styled-components';
import { tokens } from './tokens';
const Button = styled.button`
background: ${tokens.color.primary};
padding: ${tokens.spacing[4]};
font-size: ${tokens.fontSize.base};
`;
Tailwind CSS Integration
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: '#0066ff',
text: '#1a1a1a'
},
spacing: {
'4': '1rem'
},
fontSize: {
base: '1rem'
}
}
}
}
JSON Token Format (Style Dictionary)
// tokens.json
{
"color": {
"primary": {
"value": "#0066ff",
"type": "color"
},
"text": {
"value": "#1a1a1a",
"type": "color"
}
},
"spacing": {
"4": {
"value": "1rem",
"type": "dimension"
}
}
}
Multi-Platform Tokens
Design tokens shine when you need to share design values across multiple platforms. Tools like Style Dictionary can transform a single source of truth into platform-specific formats.
Web (CSS)
:root {
--color-primary: #0066ff;
}
iOS (Swift)
extension Color {
static let primary =
Color(hex: "0066ff")
}
Android (XML)
#0066ff
React Native
export const tokens = {
colorPrimary: '#0066ff'
};
Style Dictionary Example
// config.json
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/css/",
"files": [{
"destination": "variables.css",
"format": "css/variables"
}]
},
"ios": {
"transformGroup": "ios",
"buildPath": "build/ios/",
"files": [{
"destination": "StyleDictionary.swift",
"format": "ios-swift/class.swift"
}]
},
"android": {
"transformGroup": "android",
"buildPath": "build/android/",
"files": [{
"destination": "colors.xml",
"format": "android/colors"
}]
}
}
}
Benefits of Multi-Platform Tokens:
- Single source of truth for all platforms
- Consistent design across web, iOS, Android, etc.
- Automated transformation reduces errors
- Updates propagate to all platforms at once
Tools & Workflows
Modern tools help manage, transform, and distribute design tokens across teams and platforms.
Popular Design Token Tools
Transform design tokens into any format
Design token transformation tool
Sync tokens between Figma and code
Manage design tokens in Figma
Extract and sync design tokens
Design system platform with tokens
Workflow Example
# 1. Define tokens in JSON
# tokens/colors.json
# 2. Build with Style Dictionary
npm run build-tokens
# 3. Generated outputs:
# - build/css/variables.css
# - build/ios/StyleDictionary.swift
# - build/android/colors.xml
# 4. Commit and distribute
git commit -m "Update design tokens"
npm publish
Design-to-Code Workflow
Modern Token Workflow:
- Design: Create tokens in Figma using Tokens Studio plugin
- Export: Export tokens as JSON from Figma
- Transform: Use Style Dictionary to generate platform files
- Distribute: Publish as npm package or include in repos
- Consume: Import tokens in web, iOS, Android apps
- Update: Changes in Figma propagate through the pipeline
Best Practices
Follow these best practices to create maintainable, scalable design token systems.
1. Use a Consistent Naming Convention
/* Good: Clear hierarchy and meaning */
--color-text-primary
--color-text-secondary
--color-background-primary
--spacing-component-padding
--font-size-heading-large
/* Bad: Inconsistent and unclear */
--primaryText
--bg_color
--Space-2
--large-heading
2. Separate Primitive and Semantic Tokens
/* Primitive tokens (raw values) */
--blue-500: #3b82f6;
--space-4: 1rem;
/* Semantic tokens (meaning) */
--color-primary: var(--blue-500);
--button-padding: var(--space-4);
/* This makes theming and updates easier */
3. Document Your Tokens
{
"color": {
"brand": {
"primary": {
"value": "#0066ff",
"type": "color",
"description": "Primary brand color used for main CTAs and links",
"wcag": {
"aa": "Pass on white background",
"aaa": "Fail on white background"
}
}
}
}
}
4. Version Your Token Library
// package.json
{
"name": "@company/design-tokens",
"version": "2.1.0",
"description": "Design tokens for Company products",
"files": ["build/"]
}
5. Test Token Changes
Testing Strategies:
- Visual regression testing for token updates
- Contrast ratio testing for color tokens
- Accessibility testing (WCAG compliance)
- Cross-platform testing before deployment
- Validate token JSON schema
6. Avoid Hard-Coded Values
/* Bad: Hard-coded values */
.button {
background: #0066ff;
padding: 16px;
font-size: 14px;
}
/* Good: Use tokens */
.button {
background: var(--color-primary);
padding: var(--space-4);
font-size: var(--font-size-sm);
}
7. Plan for Theming
/* Structure tokens to support themes */
:root {
--color-background: white;
--color-text: black;
}
[data-theme="dark"] {
--color-background: black;
--color-text: white;
}
/* Components work with any theme */
.card {
background: var(--color-background);
color: var(--color-text);
}
8. Keep It Simple Initially
Start Small: Begin with the essentials and expand as needed:
- Core colors (brand, text, background)
- Basic spacing scale (4-8 values)
- Essential typography (sizes, weights)
- Add more as patterns emerge in your designs
Common Pitfalls to Avoid:
- ❌ Creating too many tokens too early
- ❌ Using literal names (--blue) instead of semantic (--primary)
- ❌ Skipping documentation
- ❌ Not versioning your tokens
- ❌ Mixing implementation details with design tokens
- ❌ Inconsistent naming conventions
- ❌ Forgetting about accessibility