Skip to content

CSS/JSON Design Tokens

Design tokens are the single source of truth for design decisions—colors, spacing, typography, motion, and more. Define them once, export to multiple platforms, and keep design and code in sync. This page provides both human-readable guidance and machine-parseable specifications for AI agents and design systems.


Design tokens are the smallest indivisible elements of a design system, representing individual design decisions as data. They function as named entities that store specific visual design attributes.

Benefits:

  • Consistency: Same values everywhere, no magic numbers
  • Scalability: Change a token, update the entire system
  • Cross-platform: Export to CSS, iOS, Android, React Native from one source
  • Accessibility: Encode WCAG requirements directly into tokens
  • Machine-readable: AI agents and tools can consume structured token data

The Design Tokens Community Group released the first stable specification version (2025.10) in October 2025, establishing an industry-wide standard.

PropertyDescription
File extension.tokens or .tokens.json
Media typeapplication/design-tokens+json
Property prefix$ (dollar sign)
Required properties$value
Optional properties$type, $description, $extensions
{
"color-primary": {
"$value": "#0066cc",
"$type": "color",
"$description": "Primary brand color for interactive elements"
}
}
{
"color": {
"$description": "Color tokens",
"primary": {
"$value": "#0066cc",
"$type": "color"
},
"text": {
"default": {
"$value": "#1a1a1a",
"$type": "color"
}
}
}
}
{
"color": {
"blue-600": {
"$value": "#0066cc",
"$type": "color"
},
"primary": {
"$value": "{color.blue-600}",
"$type": "color"
}
}
}

{
"color": {
"$description": "Color system with accessibility metadata",
"primitive": {
"blue": {
"50": { "$value": "#e6f2ff", "$type": "color" },
"100": { "$value": "#cce5ff", "$type": "color" },
"500": { "$value": "#0066cc", "$type": "color" },
"600": { "$value": "#0052a3", "$type": "color" },
"700": { "$value": "#003d7a", "$type": "color" },
"900": { "$value": "#001f3f", "$type": "color" }
},
"gray": {
"50": { "$value": "#f9fafb", "$type": "color" },
"100": { "$value": "#f3f4f6", "$type": "color" },
"500": { "$value": "#6b7280", "$type": "color" },
"700": { "$value": "#374151", "$type": "color" },
"900": { "$value": "#111827", "$type": "color" }
},
"white": { "$value": "#ffffff", "$type": "color" },
"black": { "$value": "#000000", "$type": "color" }
},
"semantic": {
"text": {
"default": {
"$value": "{color.primitive.gray.900}",
"$type": "color",
"$extensions": {
"human-standards": {
"wcagContrast": "4.5:1",
"pairedWith": "color.semantic.background.default"
}
}
},
"muted": {
"$value": "{color.primitive.gray.500}",
"$type": "color",
"$extensions": {
"human-standards": {
"wcagContrast": "4.5:1",
"note": "Use only for non-essential text"
}
}
},
"inverse": {
"$value": "{color.primitive.white}",
"$type": "color"
}
},
"background": {
"default": {
"$value": "{color.primitive.white}",
"$type": "color"
},
"surface": {
"$value": "{color.primitive.gray.50}",
"$type": "color"
},
"inverse": {
"$value": "{color.primitive.gray.900}",
"$type": "color"
}
},
"interactive": {
"default": {
"$value": "{color.primitive.blue.600}",
"$type": "color",
"$extensions": {
"human-standards": {
"wcagContrast": "4.5:1 on white",
"usage": "Links, buttons"
}
}
},
"hover": {
"$value": "{color.primitive.blue.700}",
"$type": "color"
},
"active": {
"$value": "{color.primitive.blue.900}",
"$type": "color"
}
},
"status": {
"error": {
"$value": "#dc2626",
"$type": "color",
"$extensions": {
"human-standards": {
"wcagContrast": "4.5:1 on white",
"note": "Never rely on color alone for error indication"
}
}
},
"success": { "$value": "#16a34a", "$type": "color" },
"warning": { "$value": "#ca8a04", "$type": "color" },
"info": { "$value": "#0284c7", "$type": "color" }
}
}
}
}
{
"typography": {
"$description": "Typography tokens with accessibility constraints",
"fontFamily": {
"base": {
"$value": "Inter, system-ui, sans-serif",
"$type": "fontFamily"
},
"mono": {
"$value": "ui-monospace, 'Cascadia Code', monospace",
"$type": "fontFamily"
}
},
"fontSize": {
"xs": {
"$value": "0.75rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 12,
"use": "Captions, labels only",
"wcagNote": "Below minimum for body text"
}
}
},
"sm": {
"$value": "0.875rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 14 } }
},
"base": {
"$value": "1rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 16,
"use": "Body text minimum",
"wcag": "WCAG recommends 16px+ for body"
}
}
},
"lg": {
"$value": "1.125rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 18 } }
},
"xl": {
"$value": "1.25rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 20 } }
},
"2xl": {
"$value": "1.5rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 24,
"wcagLargeText": true,
"contrastRequirement": "3:1 minimum"
}
}
},
"3xl": {
"$value": "1.875rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 30, "wcagLargeText": true } }
},
"4xl": {
"$value": "2.25rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 36, "wcagLargeText": true } }
}
},
"fontWeight": {
"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": "number",
"$extensions": { "human-standards": { "use": "Headings" } }
},
"normal": {
"$value": 1.5,
"$type": "number",
"$extensions": {
"human-standards": {
"use": "Body text",
"wcag": "1.4.12 Text Spacing"
}
}
},
"relaxed": {
"$value": 1.75,
"$type": "number",
"$extensions": { "human-standards": { "use": "Long-form reading" } }
}
},
"letterSpacing": {
"tight": { "$value": "-0.025em", "$type": "dimension" },
"normal": { "$value": "0", "$type": "dimension" },
"wide": {
"$value": "0.025em",
"$type": "dimension",
"$extensions": {
"human-standards": {
"wcag": "1.4.12 requires support for 0.12em minimum"
}
}
}
}
}
}

The following primitive scale is an implementation example, not a universal layout rule. Give layout decisions semantic relationship aliases—such as attached, associated, grouped, separated, and sectional—then resolve those aliases to the project’s scale. See Spatial Rhythm, Grouping & Layout.

{
"space": {
"$description": "Spacing scale based on 4px base unit",
"0": { "$value": "0", "$type": "dimension" },
"px": { "$value": "1px", "$type": "dimension" },
"0.5": {
"$value": "0.125rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 2 } }
},
"1": {
"$value": "0.25rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 4 } }
},
"2": {
"$value": "0.5rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 8 } }
},
"3": {
"$value": "0.75rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 12 } }
},
"4": {
"$value": "1rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 16 } }
},
"5": {
"$value": "1.25rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 20 } }
},
"6": {
"$value": "1.5rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 24,
"wcag": "WCAG 2.5.8 touch target minimum"
}
}
},
"8": {
"$value": "2rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 32 } }
},
"10": {
"$value": "2.5rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 40 } }
},
"11": {
"$value": "2.75rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 44,
"wcag": "WCAG 2.5.5 touch target enhanced",
"platform": ["Apple HIG", "Material Design"]
}
}
},
"12": {
"$value": "3rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 48,
"wcag": "WCAG 2.5.5 AAA target size"
}
}
},
"16": {
"$value": "4rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 64 } }
},
"20": {
"$value": "5rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 80 } }
},
"24": {
"$value": "6rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 96 } }
}
}
}
{
"touchTarget": {
"$description": "Interactive element sizing per WCAG 2.5.5 and 2.5.8",
"size": {
"minimum": {
"$value": "1.5rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 24,
"wcag": "2.5.8 AA",
"note": "Minimum with adequate spacing"
}
}
},
"comfortable": {
"$value": "2.75rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 44,
"wcag": "2.5.5 AAA",
"platform": ["Apple HIG", "Material Design"]
}
}
},
"large": {
"$value": "3rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 48,
"wcag": "2.5.5 AAA",
"platform": ["Material Design"]
}
}
}
},
"spacing": {
"recommended": {
"$value": "0.5rem",
"$type": "dimension",
"$extensions": {
"human-standards": {
"px": 8,
"status": "product guidance",
"note": "A useful project token, not WCAG's universal gap. Validate undersized targets using the 24px spacing geometry."
}
}
}
}
}
}
{
"motion": {
"$description": "Animation and transition tokens with vestibular safety",
"duration": {
"instant": {
"$value": "0ms",
"$type": "duration",
"$extensions": {
"human-standards": { "use": "State changes, no motion" }
}
},
"fast": {
"$value": "100ms",
"$type": "duration",
"$extensions": {
"human-standards": {
"use": "Micro-interactions, hovers",
"perceptionThreshold": "Below conscious perception for some"
}
}
},
"normal": {
"$value": "200ms",
"$type": "duration",
"$extensions": {
"human-standards": {
"use": "Standard transitions",
"optimal": "Good balance of speed and clarity"
}
}
},
"slow": {
"$value": "300ms",
"$type": "duration",
"$extensions": {
"human-standards": { "use": "Larger element transitions" }
}
},
"slower": {
"$value": "500ms",
"$type": "duration",
"$extensions": {
"human-standards": { "use": "Page transitions, loading states" }
}
}
},
"easing": {
"linear": { "$value": "linear", "$type": "cubicBezier" },
"easeOut": {
"$value": "cubic-bezier(0, 0, 0.2, 1)",
"$type": "cubicBezier",
"$extensions": {
"human-standards": { "use": "Elements entering the screen" }
}
},
"easeIn": {
"$value": "cubic-bezier(0.4, 0, 1, 1)",
"$type": "cubicBezier",
"$extensions": {
"human-standards": { "use": "Elements leaving the screen" }
}
},
"easeInOut": {
"$value": "cubic-bezier(0.4, 0, 0.2, 1)",
"$type": "cubicBezier",
"$extensions": {
"human-standards": { "use": "Elements moving on screen" }
}
}
}
}
}
{
"focus": {
"$description": "Focus indicator tokens per WCAG 2.4.7 and 2.4.11",
"ring": {
"width": {
"$value": "2px",
"$type": "dimension",
"$extensions": {
"human-standards": {
"wcag": "2.4.11 Focus Not Obscured",
"note": "Visible outline thickness"
}
}
},
"offset": {
"$value": "2px",
"$type": "dimension",
"$extensions": {
"human-standards": { "note": "Gap between element and focus ring" }
}
},
"color": {
"$value": "{color.semantic.interactive.default}",
"$type": "color",
"$extensions": {
"human-standards": {
"wcag": "2.4.7 Focus Visible",
"contrast": "3:1 minimum against adjacent colors"
}
}
}
}
},
"border": {
"width": {
"default": { "$value": "1px", "$type": "dimension" },
"thick": { "$value": "2px", "$type": "dimension" }
},
"radius": {
"none": { "$value": "0", "$type": "dimension" },
"sm": {
"$value": "0.125rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 2 } }
},
"md": {
"$value": "0.375rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 6 } }
},
"lg": {
"$value": "0.5rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 8 } }
},
"xl": {
"$value": "0.75rem",
"$type": "dimension",
"$extensions": { "human-standards": { "px": 12 } }
},
"full": { "$value": "9999px", "$type": "dimension" }
}
}
}
{
"shadow": {
"$description": "Elevation and depth tokens",
"none": { "$value": "none", "$type": "shadow" },
"sm": {
"$value": {
"offsetX": "0",
"offsetY": "1px",
"blur": "2px",
"spread": "0",
"color": "rgba(0, 0, 0, 0.05)"
},
"$type": "shadow"
},
"md": {
"$value": {
"offsetX": "0",
"offsetY": "4px",
"blur": "6px",
"spread": "-1px",
"color": "rgba(0, 0, 0, 0.1)"
},
"$type": "shadow"
},
"lg": {
"$value": {
"offsetX": "0",
"offsetY": "10px",
"blur": "15px",
"spread": "-3px",
"color": "rgba(0, 0, 0, 0.1)"
},
"$type": "shadow"
},
"xl": {
"$value": {
"offsetX": "0",
"offsetY": "20px",
"blur": "25px",
"spread": "-5px",
"color": "rgba(0, 0, 0, 0.1)"
},
"$type": "shadow"
}
}
}

rules:
# Color Contrast Validation
- id: color-contrast-text
severity: error
check: "Text color has ≥4.5:1 contrast against background"
applies_to: "color.semantic.text tokens"
wcag: "1.4.3 AA"
- id: color-contrast-large-text
severity: error
check: "Large text (≥24px or ≥18.66px bold) has ≥3:1 contrast"
applies_to: "typography.fontSize.2xl and above"
wcag: "1.4.3 AA"
- id: color-contrast-ui
severity: error
check: "UI components have ≥3:1 contrast against background"
applies_to: "color.semantic.interactive, border tokens"
wcag: "1.4.11 AA"
- id: color-contrast-focus
severity: error
check: "Focus indicator has ≥3:1 contrast against adjacent colors"
applies_to: "focus.ring.color"
wcag: "2.4.7 AA"
# Typography Validation
- id: font-size-minimum
severity: warning
check: "Body text uses font-size ≥1rem (16px)"
applies_to: "Body text contexts"
wcag: "Recommended for readability"
- id: line-height-minimum
severity: warning
check: "Body line height follows the product's readability guidance"
applies_to: "Paragraph text; also test user overrides at 1.5×"
wcag: "1.4.12 requires override resilience, not a prescribed default"
# Touch Target Validation
- id: touch-target-size
severity: error
check: "Interactive elements ≥24×24 CSS px OR adequate spacing"
applies_to: "touchTarget.size tokens"
wcag: "2.5.8 AA"
- id: touch-target-spacing
severity: warning
check: "Targets below 24×24 CSS px satisfy the 24px spacing geometry"
applies_to: "touchTarget.spacing tokens"
wcag: "2.5.8 AA"
# Motion Validation
- id: motion-reduced
severity: error
check: "Motion respects prefers-reduced-motion media query"
applies_to: "motion.duration tokens"
wcag: "2.3.3 AAA"
- id: motion-duration-limit
severity: warning
check: "Animations <5 seconds or user can pause/stop"
applies_to: "All animated content"
wcag: "2.2.2 AA"
# Token Structure Validation
- id: dtcg-format
severity: error
check: "Tokens follow W3C DTCG format ($value required)"
applies_to: "All tokens"
standard: "DTCG 2025.10"
- id: semantic-naming
severity: warning
check: "Semantic tokens reference primitives, not raw values"
applies_to: "color.semantic, component tokens"
best_practice: true

:root {
/* Primitive Colors */
--color-primitive-blue-500: #0066cc;
--color-primitive-blue-600: #0052a3;
--color-primitive-gray-900: #111827;
--color-primitive-white: #ffffff;
/* Semantic Colors */
--color-text-default: var(--color-primitive-gray-900);
--color-text-muted: #6b7280;
--color-background-default: var(--color-primitive-white);
--color-interactive-default: var(--color-primitive-blue-600);
/* Typography */
--font-family-base: Inter, system-ui, sans-serif;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--font-size-2xl: 1.5rem;
--line-height-normal: 1.5;
/* Spacing */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-4: 1rem;
--space-6: 1.5rem;
/* Touch Targets */
--touch-target-minimum: 1.5rem;
--touch-target-comfortable: 2.75rem;
/* Focus */
--focus-ring-width: 2px;
--focus-ring-offset: 2px;
--focus-ring-color: var(--color-interactive-default);
/* Motion */
--duration-fast: 100ms;
--duration-normal: 200ms;
--easing-ease-out: cubic-bezier(0, 0, 0.2, 1);
}
/* Light theme (default) */
:root,
[data-theme="light"] {
--color-bg: var(--color-primitive-white);
--color-text: var(--color-primitive-gray-900);
--color-text-muted: #6b7280;
--color-surface: #f9fafb;
--color-border: #e5e7eb;
}
/* Dark theme */
[data-theme="dark"] {
--color-bg: var(--color-primitive-gray-900);
--color-text: var(--color-primitive-white);
--color-text-muted: #9ca3af;
--color-surface: #1f2937;
--color-border: #374151;
}
/* System preference */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-bg: var(--color-primitive-gray-900);
--color-text: var(--color-primitive-white);
--color-text-muted: #9ca3af;
--color-surface: #1f2937;
--color-border: #374151;
}
}
/* High contrast mode */
@media (prefers-contrast: more) {
:root {
--color-text: #000000;
--color-bg: #ffffff;
--color-text-muted: #000000;
--color-border: #000000;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
:root {
--duration-fast: 0ms;
--duration-normal: 0ms;
--duration-slow: 0ms;
}
}
/* Component-level tokens for buttons */
.btn {
/* Reference semantic tokens */
--btn-bg: var(--color-interactive-default);
--btn-text: var(--color-text-inverse, #ffffff);
--btn-border-radius: var(--border-radius-md);
--btn-padding-x: var(--space-4);
--btn-padding-y: var(--space-2);
--btn-min-height: var(--touch-target-comfortable);
--btn-font-size: var(--font-size-base);
--btn-font-weight: var(--font-weight-medium);
--btn-transition: var(--duration-fast) var(--easing-ease-out);
/* Apply tokens */
background: var(--btn-bg);
color: var(--btn-text);
border-radius: var(--btn-border-radius);
padding: var(--btn-padding-y) var(--btn-padding-x);
min-height: var(--btn-min-height);
font-size: var(--btn-font-size);
font-weight: var(--btn-font-weight);
transition: background var(--btn-transition),
box-shadow var(--btn-transition);
}
.btn:hover {
--btn-bg: var(--color-interactive-hover);
}
.btn:focus-visible {
outline: var(--focus-ring-width) solid var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
}

IF text is primary body content:
USE color.semantic.text.default (4.5:1 contrast)
IF text is secondary or supplementary:
USE color.semantic.text.muted (4.5:1 contrast)
NOTE: Don't use for critical information
IF element is interactive (button, link):
USE color.semantic.interactive.default
FOR hover: color.semantic.interactive.hover
FOR active: color.semantic.interactive.active
IF indicating an error:
USE color.semantic.status.error
ALSO provide icon or text indicator (never color alone)
IF indicating success:
USE color.semantic.status.success
ALSO provide icon or text indicator
IF creating a touch/click target:
MINIMUM: touchTarget.size.minimum (24px, WCAG 2.5.8 AA)
PREFERRED: touchTarget.size.comfortable (44px, WCAG 2.5.5 AAA)
IF target is smaller than 24px:
ENSURE the 24px WCAG spacing geometry is satisfied
IF setting body text size:
MINIMUM: typography.fontSize.base (16px)
PREFERRED: typography.fontSize.lg (18px) for extended reading
IF setting heading size:
h1: typography.fontSize.4xl (36px)
h2: typography.fontSize.3xl (30px)
h3: typography.fontSize.2xl (24px)
h4: typography.fontSize.xl (20px)
1. LABEL the relationship:
attached < associated < grouped < separated < sectional
2. RESOLVE it with the product's spacing tokens:
preserve the order; do not assume a universal ratio or pixel value
3. APPLY external spacing in the parent layout:
use gap or a composition primitive; keep component padding internal
4. VERIFY the rendered rhythm:
realistic content, repeated peers, target geometry, density, and viewports

┌─────────────────────────────────────────┐
│ COMPONENT TOKENS (Specific) │
│ button-bg, input-border, card-shadow │
│ → Reference semantic tokens │
├─────────────────────────────────────────┤
│ SEMANTIC TOKENS (Purpose) │
│ color-primary, text-default, space-md │
│ → Reference primitive tokens │
├─────────────────────────────────────────┤
│ PRIMITIVE TOKENS (Raw) │
│ blue-600, gray-900, 16px │
│ → Actual values │
└─────────────────────────────────────────┘
LayerPurposeChangesExample
PrimitiveRaw design valuesRarelyblue-600: #0052a3
SemanticMeaning and intentThemes, modescolor-primary: {blue-600}
ComponentSpecific usagePer-componentbtn-bg: {color-primary}

To change primary color from blue to green:

// Before
{ "color-primary": { "$value": "{color.primitive.blue.600}" } }
// After (one change updates entire system)
{ "color-primary": { "$value": "{color.primitive.green.600}" } }

style-dictionary.config.js
import StyleDictionary from 'style-dictionary';
export default {
source: ['tokens/**/*.tokens.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [{
destination: 'tokens.css',
format: 'css/variables',
options: {
outputReferences: true
}
}]
},
scss: {
transformGroup: 'scss',
buildPath: 'dist/scss/',
files: [{
destination: '_tokens.scss',
format: 'scss/variables'
}]
},
js: {
transformGroup: 'js',
buildPath: 'dist/js/',
files: [{
destination: 'tokens.js',
format: 'javascript/es6'
}]
},
json: {
transformGroup: 'js',
buildPath: 'dist/',
files: [{
destination: 'tokens.json',
format: 'json/nested'
}]
}
}
};
build-tokens.js
import StyleDictionary from 'style-dictionary';
const sd = new StyleDictionary('./style-dictionary.config.js');
// V4 requires await
await sd.buildAllPlatforms();
console.log('✅ Tokens built successfully');
// Add accessibility metadata to output
StyleDictionary.registerTransform({
name: 'custom/a11y-comment',
type: 'value',
filter: (token) => token.$extensions?.['human-standards'],
transform: (token) => {
const meta = token.$extensions['human-standards'];
const comment = meta.wcag ? ` /* WCAG ${meta.wcag} */` : '';
return token.$value + comment;
}
});

  • Use W3C DTCG format ($value, $type, $description)
  • Organize in three layers (primitive → semantic → component)
  • Include accessibility metadata in $extensions
  • Document WCAG requirements per token
  • Define all primitive colors with sufficient range
  • Create semantic tokens for text, background, interactive, status
  • Pair text/background tokens with contrast ratios documented
  • Include dark mode and high contrast variations
  • Set body text minimum at 16px (1rem)
  • Document which sizes qualify as “large text” (24px+)
  • Include line-height tokens (1.5 minimum for body)
  • Define letter-spacing that supports WCAG 1.4.12
  • Define a project-appropriate primitive scale; do not treat its base unit as layout semantics
  • Map semantic relationships to tokens while preserving attached < associated < grouped < separated < sectional
  • Include WCAG touch target sizes (24px minimum, 44px comfortable)
  • Document WCAG target geometry separately from product-recommended gaps
  • Configure Style Dictionary 4+ for DTCG format
  • Export to all required platforms (CSS, JS, iOS, Android)
  • Include theme mode support (light, dark, high contrast)
  • Support prefers-reduced-motion
  • Automated contrast checking in CI
  • Token naming consistency linting
  • DTCG format validation
  • Documentation generation from token metadata

MistakeProblemSolution
Hard-coded valuesInconsistency, hard to maintainAlways use tokens, never magic numbers
Missing semantic layerCan’t change themes, no meaningAdd semantic tokens between primitives and components
No contrast metadataAccessibility issues missedDocument contrast ratios in $extensions
Ignoring reduced motionVestibular issues for some usersInclude motion: 0 for prefers-reduced-motion
Raw values in semanticBreaks abstractionSemantic tokens should reference primitives
No documentationTokens misusedUse $description and $extensions
Inconsistent namingConfusion, conflictsFollow consistent naming convention
Platform-specific valuesCross-platform breaksUse rem/unitless, transform per platform

The Design Tokens Community Group released the first stable specification (2025.10) in October 2025, with contributions from Adobe, Amazon, Google, Microsoft, Meta, Figma, and many others. This standardizes token interchange format.

Style Dictionary 4 released with first-class DTCG support, async API, better error handling, and token expansion for composite values.

Enterprise design systems research shows that semantic tokens (like action-primary instead of blue-500) improve accessibility compliance at scale by making it easier to audit and update contrast-compliant color pairs.

Current WCAG contrast formulas assume sRGB color space. As displays support wider gamuts (P3, Rec2020), contrast tools are evolving but not yet standardized for new color spaces.

In April 2024, the US Department of Justice updated Title II of the ADA, mandating WCAG 2.1 AA compliance for government websites and mobile apps. The DOJ extended both compliance deadlines by a year on 17 April 2026 — now 26 April 2027 for entities serving populations of 50,000+ and 26 April 2028 for smaller entities. See Standards & Guidelines.


Official Standards:

Tooling:

Platform Guidelines:

Research & Best Practices: