TLDR
Style Dictionary is Amazon's open-source build system that transforms design tokens from JSON source files into platform-specific outputs like CSS variables, SCSS, JavaScript, iOS Swift, and Android XML. It acts as the "compiler" for your design system, ensuring tokens stay synchronized across all platforms.
Key takeaways:
- Style Dictionary is the industry-standard tool for design tokens at scale
- Write tokens once in JSON, generate outputs for all platforms (web, iOS, Android, React Native)
- Built-in transforms handle common conversions (px to rem, hex to RGB, camelCase to kebab-case)
- Custom transforms and formats let you adapt to any tech stack or naming convention
- Integrates with Figma Tokens plugin for design-to-code automation
- Powers design systems at Amazon, Adobe, Salesforce, and thousands of other companies
What is Style Dictionary?
Style Dictionary is a build tool created by Amazon for their design system. It solves a fundamental problem: design tokens need to exist in multiple formats for different platforms, but manually maintaining separate files (CSS, SCSS, JavaScript, iOS, Android) leads to inconsistencies and errors. This makes it essential for teams practicing design system handoff across multiple platforms.
Instead of writing this:
colors.css:
:root {
--color-primary: #3b82f6;
}colors.scss:
$color-primary: #3b82f6;colors.js:
export const colorPrimary = '#3b82f6';Colors.swift:
let colorPrimary = UIColor(hex: "3b82f6")You write tokens once in JSON:
{
"color": {
"primary": {
"value": "#3b82f6"
}
}
}Then Style Dictionary generates all platform outputs automatically. Change the primary color in one place, rebuild, and every platform updates simultaneously.
This is transformative for teams working across web, iOS, and Android. Your designers define tokens once, and developers consume them in their native format without manual translation.
Installation and Project Setup
Style Dictionary is an npm package. Install it in your project:
npm install style-dictionary --save-devOr with pnpm:
pnpm add -D style-dictionaryDirectory Structure
Create two directories:
project/
├── tokens/ # Source token files (JSON)
│ ├── colors.json
│ ├── spacing.json
│ ├── typography.json
│ └── ...
├── build/ # Generated output (CSS, SCSS, etc.)
├── style-dictionary.config.json
└── package.json
tokens/ contains your source of truth—the JSON files defining your design tokens.
build/ is where Style Dictionary writes generated outputs. This directory should be in .gitignore because it's auto-generated.
Initial Configuration
Create style-dictionary.config.json in your project root:
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/css/",
"files": [{
"destination": "variables.css",
"format": "css/variables"
}]
}
}
}This minimal config tells Style Dictionary:
- Read all
.jsonfiles intokens/ - Generate CSS custom properties in
build/css/variables.css
Defining Your Token Files
Design tokens should follow the W3C Design Tokens Community Group format. Each token has a value and optional metadata like type, description, and attributes.
Complete colors.json Example
{
"color": {
"brand": {
"primary": {
"value": "#3b82f6",
"type": "color",
"description": "Primary brand color used for CTAs and links"
},
"secondary": {
"value": "#8b5cf6",
"type": "color"
}
},
"neutral": {
"50": { "value": "#f9fafb", "type": "color" },
"100": { "value": "#f3f4f6", "type": "color" },
"200": { "value": "#e5e7eb", "type": "color" },
"300": { "value": "#d1d5db", "type": "color" },
"400": { "value": "#9ca3af", "type": "color" },
"500": { "value": "#6b7280", "type": "color" },
"600": { "value": "#4b5563", "type": "color" },
"700": { "value": "#374151", "type": "color" },
"800": { "value": "#1f2937", "type": "color" },
"900": { "value": "#111827", "type": "color" }
},
"semantic": {
"background": {
"primary": {
"value": "{color.neutral.50}",
"type": "color",
"description": "Default page background"
},
"secondary": {
"value": "{color.neutral.100}",
"type": "color"
}
},
"text": {
"primary": {
"value": "{color.neutral.900}",
"type": "color"
},
"secondary": {
"value": "{color.neutral.600}",
"type": "color"
}
}
}
}
}Key patterns:
- Hierarchical naming: Organize tokens in logical groups (
color.brand,color.neutral,color.semantic) - References: Use
{color.neutral.50}to reference other tokens. Style Dictionary resolves these during build. - Semantic layer:
color.semantic.background.primaryreferencescolor.neutral.50. This indirection lets you change the base palette without touching semantic tokens.
Complete spacing.json Example
{
"spacing": {
"0": { "value": "0", "type": "spacing" },
"1": { "value": "4px", "type": "spacing" },
"2": { "value": "8px", "type": "spacing" },
"3": { "value": "12px", "type": "spacing" },
"4": { "value": "16px", "type": "spacing" },
"6": { "value": "24px", "type": "spacing" },
"8": { "value": "32px", "type": "spacing" },
"12": { "value": "48px", "type": "spacing" },
"16": { "value": "64px", "type": "spacing" },
"24": { "value": "96px", "type": "spacing" },
"component": {
"button": {
"padding-x": {
"value": "{spacing.4}",
"type": "spacing"
},
"padding-y": {
"value": "{spacing.2}",
"type": "spacing"
}
}
}
}
}Complete typography.json Example
{
"font": {
"family": {
"base": {
"value": "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
"type": "fontFamily"
},
"mono": {
"value": "'Fira Code', 'Courier New', monospace",
"type": "fontFamily"
}
},
"size": {
"xs": { "value": "12px", "type": "fontSize" },
"sm": { "value": "14px", "type": "fontSize" },
"base": { "value": "16px", "type": "fontSize" },
"lg": { "value": "18px", "type": "fontSize" },
"xl": { "value": "20px", "type": "fontSize" },
"2xl": { "value": "24px", "type": "fontSize" },
"3xl": { "value": "30px", "type": "fontSize" }
},
"weight": {
"normal": { "value": "400", "type": "fontWeight" },
"medium": { "value": "500", "type": "fontWeight" },
"semibold": { "value": "600", "type": "fontWeight" },
"bold": { "value": "700", "type": "fontWeight" }
},
"lineHeight": {
"tight": { "value": "1.25", "type": "lineHeight" },
"normal": { "value": "1.5", "type": "lineHeight" },
"relaxed": { "value": "1.75", "type": "lineHeight" }
}
}
}Pro tip: Use the type field consistently. It helps Style Dictionary apply correct transforms (e.g., only transform color types through color conversion).
Configuration Deep Dive
The style-dictionary.config.json file controls how tokens are transformed and where output files are written.
Complete Multi-Platform Configuration
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/css/",
"files": [
{
"destination": "variables.css",
"format": "css/variables",
"options": {
"outputReferences": true
}
}
]
},
"scss": {
"transformGroup": "scss",
"buildPath": "build/scss/",
"files": [
{
"destination": "_variables.scss",
"format": "scss/variables",
"options": {
"outputReferences": true
}
}
]
},
"js": {
"transformGroup": "js",
"buildPath": "build/js/",
"files": [
{
"destination": "tokens.js",
"format": "javascript/es6"
},
{
"destination": "tokens.d.ts",
"format": "typescript/es6-declarations"
}
]
},
"ios": {
"transformGroup": "ios",
"buildPath": "build/ios/",
"files": [
{
"destination": "StyleDictionary.swift",
"format": "ios-swift/class.swift",
"className": "StyleDictionary"
}
]
},
"android": {
"transformGroup": "android",
"buildPath": "build/android/",
"files": [
{
"destination": "colors.xml",
"format": "android/colors"
}
]
}
}
}Key Configuration Options
transformGroup: Pre-configured set of transforms for a platform. Available groups:
css– Converts to kebab-case, addspxsuffix, outputs CSS custom propertiesscss– SCSS variable format with$prefixjs– JavaScript constants in ES6 formatios– Swift naming conventionsandroid– Android XML resource format
outputReferences (critical!):
"options": {
"outputReferences": true
}This tells Style Dictionary to preserve references in the output. Instead of:
:root {
--color-neutral-50: #f9fafb;
--color-background-primary: #f9fafb; /* duplicate value */
}You get:
:root {
--color-neutral-50: #f9fafb;
--color-background-primary: var(--color-neutral-50); /* reference preserved */
}Now changing --color-neutral-50 automatically updates --color-background-primary. This is essential for maintaining the semantic token architecture.
Code Example: Complete Build Pipeline
Here's a full working example from token definition to generated output.
1. Define tokens (tokens/colors.json):
{
"color": {
"base": {
"blue": { "value": "#3b82f6" }
},
"semantic": {
"primary": { "value": "{color.base.blue}" }
}
}
}2. Configure build (style-dictionary.config.json):
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/css/",
"files": [{
"destination": "variables.css",
"format": "css/variables",
"options": { "outputReferences": true }
}]
}
}
}3. Add build script (package.json):
{
"scripts": {
"build:tokens": "style-dictionary build"
}
}4. Run build:
npm run build:tokens5. Generated output (build/css/variables.css):
/**
* Do not edit directly
* Generated on [timestamp]
*/
:root {
--color-base-blue: #3b82f6;
--color-semantic-primary: var(--color-base-blue);
}6. Use in your CSS:
.button-primary {
background-color: var(--color-semantic-primary);
}This pipeline is the foundation. You define tokens once, run the build, and consume generated output in your application.
Custom Transforms and Formats
Style Dictionary's real power comes from custom transforms. You can modify token names, values, or attributes to match your exact requirements.
Custom Transform: px to rem
Many teams prefer rem units over px for accessibility. Here's how to create a custom transform:
build-tokens.js:
const StyleDictionary = require('style-dictionary');
// Register custom transform
StyleDictionary.registerTransform({
name: 'size/pxToRem',
type: 'value',
matcher: (token) => {
return token.type === 'spacing' || token.type === 'fontSize';
},
transformer: (token) => {
const val = parseFloat(token.value);
if (isNaN(val)) return token.value;
return `${val / 16}rem`;
}
});
// Create custom transform group with our transform
StyleDictionary.registerTransformGroup({
name: 'custom/css',
transforms: [
'attribute/cti',
'name/cti/kebab',
'size/pxToRem', // Our custom transform
'color/css'
]
});
// Build with custom config
const sd = StyleDictionary.extend({
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'custom/css',
buildPath: 'build/css/',
files: [{
destination: 'variables.css',
format: 'css/variables',
options: { outputReferences: true }
}]
}
}
});
sd.buildAllPlatforms();Run the custom build:
{
"scripts": {
"build:tokens": "node build-tokens.js"
}
}Input (tokens/spacing.json):
{
"spacing": {
"4": { "value": "16px", "type": "spacing" }
}
}Output (build/css/variables.css):
:root {
--spacing-4: 1rem; /* 16px converted to rem */
}Custom Format: Tailwind Theme
You can create custom formats to generate any output structure. Here's a format that generates a Tailwind config:
StyleDictionary.registerFormat({
name: 'tailwind/theme',
formatter: (dictionary) => {
const colors = {};
dictionary.allTokens
.filter(token => token.type === 'color')
.forEach(token => {
const path = token.path.slice(1); // Remove 'color' prefix
let current = colors;
path.forEach((key, i) => {
if (i === path.length - 1) {
current[key] = token.value;
} else {
current[key] = current[key] || {};
current = current[key];
}
});
});
return `module.exports = {
theme: {
extend: {
colors: ${JSON.stringify(colors, null, 2)}
}
}
}`;
}
});This lets you maintain tokens in Style Dictionary format but output a Tailwind-compatible theme file.
Integrating with Figma Tokens Plugin
The Figma Tokens plugin lets designers manage design tokens directly in Figma and export them as JSON. Combined with Style Dictionary, this creates a fully automated design-to-code pipeline.
Workflow:
- Designer: Define tokens in Figma Tokens plugin (colors, spacing, typography)
- Designer: Export tokens as JSON to project repository
- Developer: Commit JSON files to
tokens/directory - CI/CD: Run
style-dictionary buildautomatically - Developer: Import generated CSS/SCSS/JS into application
Setup steps:
- Install Figma Tokens plugin in Figma
- Define your tokens in the plugin UI
- Set export location to sync with your repository (GitHub sync recommended)
- Configure Style Dictionary to read the exported JSON format
Example Figma Tokens export:
{
"global": {
"colors": {
"primary": {
"value": "#3b82f6",
"type": "color"
}
}
}
}This format is already compatible with Style Dictionary's expected structure. You may need to write a simple transform to flatten the global wrapper if your token structure differs.
Pro tip: Use Figma Tokens' JSON schema validation to prevent invalid token definitions before they reach Style Dictionary. This catches errors at design time rather than build time.
Watch Mode for Development
During development, you don't want to manually rebuild tokens after every change. Add a watch script:
package.json:
{
"scripts": {
"build:tokens": "style-dictionary build",
"watch:tokens": "style-dictionary build --watch"
}
}Run npm run watch:tokens and Style Dictionary will automatically rebuild whenever you change a token JSON file.
Pro tip: Combine this with your dev server's hot reload. In Next.js, for example, changing the generated CSS file triggers a hot reload, so you see token changes immediately in the browser.
Design Token Architecture Best Practices
After setting up hundreds of design systems with Style Dictionary, these patterns emerge:
1. Three-tier token architecture:
- Base tokens: Raw values (
color.blue.500: #3b82f6) - Semantic tokens: Contextual names (
color.primary: {color.blue.500}) - Component tokens: Component-specific (
button.background: {color.primary})
2. Always use outputReferences: true to preserve token relationships in generated code
3. Keep token files small and focused (one file per category: colors, spacing, typography)
4. Use type field consistently so transforms work correctly
5. Version your tokens in git and tag releases when making breaking changes
For more on design token architecture and implementation patterns, see our guide on design tokens in JSON format and how they generate CSS variables.
FAQ
Q: How do I create custom transforms in Style Dictionary?
A: Register custom transforms using StyleDictionary.registerTransform() with a name, type (attribute, name, or value), and transformer function. For example, to convert pixels to rems, create a value transform that divides the original value by 16. Custom transforms run during the build process and can modify token attributes, names, or values.
Q: Can Style Dictionary integrate with Figma Tokens plugin?
A: Yes. Export your tokens from Figma Tokens plugin as JSON, place the files in your Style Dictionary tokens/ directory, and run the build. You may need to write custom transforms to convert Figma-specific token formats to your desired output format. This workflow keeps Figma as the source of truth while automating the export to code.
Q: What output formats does Style Dictionary support?
A: Style Dictionary supports CSS custom properties, SCSS variables, JavaScript/TypeScript modules, JSON, iOS Swift constants, Android XML resources, and more. You can also create custom formats for specific needs like Tailwind theme files or React Native style objects. Each platform can have multiple output formats.