How to encode dark mode typography adjustments as design tokens
- Step 1Define light mode tokens — tokens.json: { 'font-weight-body': { '$value': 400, '$type': 'fontWeight' }, 'letter-spacing-body': { '$value': 0 } }. The default values for light mode.
- Step 2Define dark mode overrides — tokens.dark.json: { 'font-weight-body': { '$value': 350 }, 'letter-spacing-body': { '$value': '0.01em' } }. Only the values that differ from light.
- Step 3Build with media query — Build script emits :root { defaults } + @media (prefers-color-scheme: dark) { :root { dark overrides } }. CSS variables shift automatically when the media query matches.
Frequently asked questions
What about manual mode override?+
Add [data-theme="dark"] :root { ... } alongside the media query. Manual override beats system preference — useful for theme switchers in user settings.
Should every property differ between modes?+
No — most don't change. Only weight, letter-spacing, line-height, and colour. Font-family, sizes, and most other typography stays constant. Override only what needs to change.
Can I theme cross-platform?+
Yes — Style Dictionary's mode-aware transforms emit per-platform mode handling: media queries for web, UIUserInterfaceStyle for iOS, night-* resource folders for Android. Same source.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.