How to subset fonts for a multilingual design system
- Step 1Inventory your supported languages — List the locales your product targets. Group by Unicode subset: Latin Basic, Latin Extended, Cyrillic, Greek, Arabic, Devanagari, CJK Simplified, CJK Traditional. Most SaaS products end up with 5–8 distinct subsets.
- Step 2Subset per language — Run the JAD Subsetter once per subset against your brand font. Output: brand-latin.woff2, brand-latin-ext.woff2, brand-cyrillic.woff2, etc. Each is independently sized to its locale's needs.
- Step 3Emit unicode-range @font-face — One @font-face block per subset, each with the matching unicode-range. The browser fetches only what it needs based on rendered characters. Visit an English page → download Latin only. Switch to Russian → download Cyrillic.
Frequently asked questions
What about CJK languages?+
CJK fonts are uniquely large (5,000+ glyphs for common usage). Subset to commonly-used codepoints (JIS Level 1 for Japanese, GB2312 for Simplified Chinese, KS X 1001 for Korean) to drop from 5+ MB to 1 MB. Visitors who type rare characters fall back to system fonts gracefully.
Should I match Google Fonts' subset boundaries?+
Yes — Google's subset definitions are well-tested across real-world traffic. Mimicking their unicode-range boundaries means you can swap your self-hosted fonts in for Google Fonts without changing CSS.
Does unicode-range work for emoji?+
Yes — emoji codepoints (U+1F300–U+1FAFF) can be a separate subset. Most apps don't ship custom emoji fonts and rely on the OS instead, but for branded emoji, unicode-range loading is a clean pattern.
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.