Design Tokens: Why Your Design System Needs Them
Right, so design tokens. If you've been building design systems for a while, you've probably heard this term thrown around heaps. But what are they actually, and why should you care?
Let me break it down for you.
What Are Design Tokens Actually?
Design tokens are basically named variables that store your design decisions. Think of them as the building blocks of your design system. Instead of hardcoding colours and spacing everywhere, you create reusable values that any platform can understand.
Here's a simple example:
{
"color": {
"primary": {
"500": "#3B82F6",
"600": "#2563EB",
"700": "#1D4ED8"
}
},
"spacing": {
"xs": "4px",
"sm": "8px",
"md": "16px",
"lg": "24px"
}
}
Breaking Down Different Types of Tokens
1. Colour Tokens
Your brand colours and semantic meanings all in one place:
{
"color": {
"brand": {
"primary": "#3B82F6",
"secondary": "#10B981"
},
"semantic": {
"success": "#059669",
"warning": "#D97706",
"error": "#DC2626",
"info": "#0284C7"
},
"neutral": {
"50": "#F9FAFB",
"100": "#F3F4F6",
"900": "#111827"
}
}
}
2. Typography Tokens
Keep your text styling consistent across everything:
{
"typography": {
"fontFamily": {
"sans": ["Inter", "system-ui", "sans-serif"],
"mono": ["Fira Code", "monospace"]
},
"fontSize": {
"xs": "12px",
"sm": "14px",
"base": "16px",
"lg": "18px",
"xl": "20px",
"2xl": "24px"
},
"fontWeight": {
"normal": "400",
"medium": "500",
"semibold": "600",
"bold": "700"
}
}
}
3. Spacing Tokens
This is where the magic happens. Consistent spacing throughout your entire app:
{
"spacing": {
"0": "0px",
"1": "4px",
"2": "8px",
"3": "12px",
"4": "16px",
"5": "20px",
"6": "24px",
"8": "32px",
"10": "40px",
"12": "48px",
"16": "64px"
}
}
4. Border Radius Tokens
Because nobody wants wonky rounded corners:
{
"borderRadius": {
"none": "0px",
"sm": "2px",
"md": "4px",
"lg": "8px",
"xl": "12px",
"full": "9999px"
}
}
How to Organise Your Tokens
Global Tokens
These are your base values that rarely change:
{
"color": {
"blue": {
"500": "#3B82F6"
}
}
}
Alias Tokens
These reference your global tokens but give them meaning:
{
"color": {
"action": {
"primary": "{color.blue.500}"
}
}
}
Component Tokens
Specific values for individual components:
{
"button": {
"primary": {
"background": "{color.action.primary}",
"text": "{color.white}"
}
}
}
Putting Tokens to Work
Alright, you've got your tokens defined. Now what? Let's look at how to actually implement them in your projects.
1. The Style Dictionary Way
Style Dictionary is probably the most popular tool for this stuff. It's an Amazon open-source project that takes your design tokens (written in JSON) and transforms them into whatever format you need. CSS variables, SCSS, JavaScript objects, iOS Swift files, Android XML - you name it.
The beauty of Style Dictionary is that you write your tokens once and it spits out platform-specific files. So your mobile team gets their native formats while your web team gets CSS variables.
Here's how you set it up:
// config.json
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "dist/css/",
"files": [{
"destination": "variables.css",
"format": "css/variables"
}]
},
"js": {
"transformGroup": "js",
"buildPath": "dist/js/",
"files": [{
"destination": "tokens.js",
"format": "javascript/es6"
}]
},
"ios": {
"transformGroup": "ios",
"buildPath": "dist/ios/",
"files": [{
"destination": "tokens.swift",
"format": "ios-swift/class.swift"
}]
}
}
}
Run style-dictionary build and boom - you've got tokens for every platform.
It's pretty neat once you get the hang of it.
2. Good Old CSS Variables
Turn your tokens into CSS custom properties:
:root {
--color-primary-500: #3b82f6;
--color-primary-600: #2563eb;
--spacing-4: 16px;
--spacing-8: 32px;
--border-radius-md: 4px;
}
.button {
background-color: var(--color-primary-500);
padding: var(--spacing-4);
border-radius: var(--border-radius-md);
}
3. JavaScript/TypeScript Objects
Export them as proper objects you can use in your code:
export const tokens = {
color: {
primary: {
500: '#3B82F6',
600: '#2563EB',
},
},
spacing: {
4: '16px',
8: '32px',
},
} as const;
// Usage in React
const Button = () => (
<button
style={{
backgroundColor: tokens.color.primary[500],
padding: tokens.spacing[4],
}}
>
Click me
</button>
);
Getting Fancy with Tokens
1. Responsive Tokens
Different values for different screen sizes:
{
"spacing": {
"section": {
"mobile": "24px",
"tablet": "32px",
"desktop": "48px"
}
}
}
2. Theme Tokens
Light mode, dark mode, whatever mode:
{
"theme": {
"light": {
"background": "#FFFFFF",
"text": "#111827"
},
"dark": {
"background": "#111827",
"text": "#F9FAFB"
}
}
}
3. Complex Tokens
Sometimes you need tokens that combine multiple properties:
{
"shadow": {
"sm": {
"x": "0px",
"y": "1px",
"blur": "2px",
"spread": "0px",
"color": "{color.neutral.900}",
"opacity": "0.05"
}
}
}
Tools Worth Using
Popular Token Tools
- Tokens Studio (formerly Figma Tokens Plugin) - Pull and manage tokens in Figma
- Style Dictionary - Transform tokens for any platform
Real Examples
Tailwind CSS Integration
// tailwind.config.js
const tokens = require('./tokens.json');
module.exports = {
theme: {
colors: tokens.color,
spacing: tokens.spacing,
borderRadius: tokens.borderRadius,
fontFamily: tokens.typography.fontFamily,
},
};
Styled Components Integration
import styled, { ThemeProvider } from 'styled-components';
import { tokens } from './tokens';
const Button = styled.button`
background-color: ${(props) => props.theme.color.primary[500]};
padding: ${(props) => props.theme.spacing[4]};
border-radius: ${(props) => props.theme.borderRadius.md};
`;
// Usage
<ThemeProvider theme={tokens}>
<Button>Click me</Button>
</ThemeProvider>;
Don't Make These Mistakes
1. Name Things Properly
Use names that make sense:
{
"color": {
"text": {
"primary": "#111827",
"secondary": "#6B7280",
"disabled": "#9CA3AF"
}
}
}
2. Meaning Over Appearance
Don't name things after how they look:
// ❌ Avoid
{
"color": {
"blue500": "#3B82F6"
}
}
// ✅ Prefer
{
"color": {
"action": {
"primary": "#3B82F6"
}
}
}
3. Keep It Organised
Structure your tokens in a way that makes sense:
{
"component": {
"button": {
"primary": {
"background": {
"default": "{color.action.primary}",
"hover": "{color.action.primaryHover}",
"disabled": "{color.neutral.300}"
}
}
}
}
}
How This Actually Works in Practice
1. Design Phase
- Set up your tokens in Figma or Sketch
- Use plugins to keep everything consistent
- Document how people should use them
2. Development Phase
- Transform tokens into whatever format you need
- Hook them into your build process
- Make sure everyone knows how to use them
3. Maintenance Phase
- Version control your changes properly
- Test that nothing breaks when you update
- Keep your docs up to date
Common Problems and How to Fix Them
Version Control
Use proper versioning for your token updates:
{
"version": "2.1.0",
"tokens": {
// token definitions
}
}
Breaking Changes
When you need to deprecate old tokens:
{
"color": {
"primary": "#3B82F6", // deprecated: use color.action.primary
"action": {
"primary": "#3B82F6"
}
}
}
Platform Differences
Different platforms need different formats:
// iOS
const iosTokens = {
colorPrimary500: UIColor(red: 59/255, green: 130/255, blue: 246/255, alpha: 1)
};
// Android
const androidTokens = {
color_primary_500: "#3B82F6"
};
How to Know If It's Working
Track a few key things:
- Consistency - Are things looking the same across platforms?
- Speed - How quickly can you implement new features?
- Maintenance - How much effort does it take to update designs?
- Adoption - Are people actually using the tokens?
What's Coming Next
The token world is moving pretty fast:
- W3C Spec - They're working on standardising this stuff
- AI Generation - AI tools that can create tokens automatically
- Real-time Sync - Live updates between design and code
- Smart Theming - Context-aware token selection
Wrapping Up
Look, design tokens aren't just fancy variables. They're the backbone of any decent design system. Get them right, and you'll save yourself heaps of time and headaches down the track.
Here's what you get when you do this properly:
- Everything looks consistent without you having to think about it
- Updates are easy. Change one value, update everywhere
- New features get built faster
- Less maintenance overhead
Start small with just colours and spacing. Once you've got the hang of it, expand to typography, shadows, and component-specific stuff. Trust me, the time you invest upfront pays off big time later.
The design world is moving towards tokens whether you like it or not, so you might as well get on board now. Your future self will thank you for it.