W3C Design Tokens Format
When to Use
Use this when you need a vendor-neutral interchange format for sharing tokens across tools (Figma, Style Dictionary, Tailwind, native apps). The DTCG specification reached its first stable version (2025.10) in October 2025.
Composite Types
The spec supports complex design properties (shadows, typography, borders) that combine multiple sub-values. Shadow example:
{
"shadow": {
"card": {
"$value": { "offsetX": "0px", "offsetY": "2px", "blur": "8px",
"spread": "0px", "color": "{color.neutral}" },
"$type": "shadow"
}
}
}
Decision
| Token Type | $type Value | Example $value |
|---|---|---|
| Color | color | "oklch(55% 0.3 240)" |
| Dimension | dimension | "0.5rem" |
| Font family | fontFamily | ["Inter", "system-ui", "sans-serif"] |
| Font weight | fontWeight | "600" |
| Duration | duration | "200ms" |
| Cubic bezier | cubicBezier | [0.4, 0, 0.2, 1] |
| Shadow | shadow | { offsetX, offsetY, blur, spread, color } |
| Border | border | { color, width, style } |
| Typography | typography | { fontFamily, fontSize, lineHeight, ... } |
Pattern
Token File Structure
Files use .tokens.json extension and application/design-tokens+json media type.
{
"color": {
"primary": {
"$value": "oklch(55% 0.3 240)",
"$type": "color",
"$description": "Main brand action color"
},
"primary-content": {
"$value": "oklch(98% 0.01 240)",
"$type": "color"
}
},
"spacing": {
"sm": { "$value": "0.5rem", "$type": "dimension" },
"md": { "$value": "1rem", "$type": "dimension" },
"lg": { "$value": "1.5rem", "$type": "dimension" }
},
"font-family": {
"sans": {
"$value": ["Inter", "system-ui", "sans-serif"],
"$type": "fontFamily"
}
},
"border-radius": {
"field": { "$value": "0.5rem", "$type": "dimension" },
"box": { "$value": "1rem", "$type": "dimension" }
}
}
Token Aliases
Tokens reference other tokens with curly braces: "$value": "{color.blue-500}". This creates a dependency chain resolved at build time by tools like Style Dictionary.
Composite Types
Shadow example:
{
"shadow": {
"card": {
"$value": { "offsetX": "0px", "offsetY": "2px", "blur": "8px",
"spread": "0px", "color": "{color.neutral}" },
"$type": "shadow"
}
}
}
Conversion to Tailwind v4
Use Style Dictionary or a simple script to flatten DTCG JSON into @theme variables:
// dtcg-to-tailwind.mjs
import { readFileSync } from 'fs';
const tokens = JSON.parse(readFileSync('tokens.tokens.json', 'utf8'));
function toThemeVars(obj, prefix = '') {
let vars = [];
for (const [key, val] of Object.entries(obj)) {
const path = prefix ? `${prefix}-${key}` : key;
if (val.$value !== undefined) vars.push(` --${path}: ${val.$value};`);
else vars.push(...toThemeVars(val, path));
}
return vars;
}
console.log(`@theme {\n${toThemeVars(tokens).join('\n')}\n}`);
Common Mistakes
- Wrong: Using custom $type values not in the spec. Right: Stick to official types for tool compatibility.
- Wrong: Circular alias references. Right: Maintain a directed acyclic graph of token dependencies.
See Also
- Figma to Tailwind Mapping
- Token Naming Conventions
- Reference: https://www.designtokens.org/tr/drafts/format/