Font Subsetting Strategies
Learn when and how to subset fonts for maximum performance. Compare full fonts vs subsets, implement unicode-range splitting, and understand dynamic subsetting approaches.
Key Takeaways
- • Subsetting can reduce font sizes by 50-90%
- • Use unicode-range to load only needed character sets
- • Latin-only subset: ~15KB vs full font: ~150KB
- • Balance between file size and flexibility
In this article
When to Subset Fonts
Subsetting removes unused characters from font files. It is most effective when you know exactly which characters you will need.
Good Candidates for Subsetting
- ✓Single-language sites - English-only needs only Latin characters
- ✓Logo/brand fonts - Only company name characters needed
- ✓Heading fonts - Limited vocabulary, predictable content
- ✓CJK fonts - Huge savings by limiting to common characters
Avoid Over-Subsetting
- ✗User-generated content - Can not predict needed characters
- ✗Multi-language apps - May need full character sets
- ✗Dynamic content - Characters may vary per page
- ✗Aggressive Latin-only - May break accented names
Unicode-Range Strategy
Split fonts into subsets by unicode range. Browsers only download subsets containing characters used on the page.
/* Split font into language subsets */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-latin.woff2') format('woff2');
unicode-range: U+0000-00FF; /* Basic Latin */
font-display: swap;
}
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F; /* Latin Extended */
font-display: swap;
}
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-cyrillic.woff2') format('woff2');
unicode-range: U+0400-04FF; /* Cyrillic */
font-display: swap;
}
/* Browser only downloads subsets needed for page content */Common Unicode Ranges
| Range | Name | Characters |
|---|---|---|
| U+0000-00FF | Basic Latin | A-Z, a-z, 0-9, punctuation |
| U+0100-024F | Latin Extended | Accented characters (é, ñ, ü) |
| U+0400-04FF | Cyrillic | Russian, Ukrainian, etc. |
| U+0370-03FF | Greek | Greek alphabet |
| U+4E00-9FFF | CJK Unified | Chinese, Japanese, Korean |
Size Comparison
~150KB
Full Font
All glyphs, all languages
~40KB
Latin Extended
Western European languages
~15KB
Basic Latin Only
English characters only
CJK Savings
Chinese/Japanese/Korean fonts can be 5-20MB. Subsetting to common characters reduces to 200-500KB—a 90-97% reduction.
Dynamic Subsetting
For applications with dynamic content, generate subsets on-demand based on actual content.
// Example: Build-time text extraction
const fs = require('fs');
const glob = require('glob');
// Extract all text from HTML/JSX files
const files = glob.sync('src/**/*.{html,jsx,tsx}');
const allText = files
.map(f => fs.readFileSync(f, 'utf8'))
.join('');
// Get unique characters
const chars = [...new Set(allText)].join('');
// Use with subsetting tool
// pyftsubset font.ttf --text="${chars}" --output-file=font-subset.woff2Google Fonts API
Google Fonts automatically subsets based on the text parameter.
<!-- Only include characters in "Hello World" --> <link href="https://fonts.googleapis.com/css2?family=Roboto&text=Hello%20World" rel="stylesheet"> <!-- Result: Tiny font file with only needed glyphs -->
Best Practices
Always Include These Characters
Even for basic Latin, include: punctuation (!@#$%...), numbers (0-9), common symbols (©®™), and currency ($ € £ ¥).
Test Thoroughly
Check for missing glyphs (displayed as □ or tofu). Test with real content, user names, and edge cases.
Preserve OpenType Features
When subsetting, preserve ligatures, kerning, and other OpenType features you use.
Language-Specific Guides
Subset Your Fonts Now
Use our free tool to subset fonts and reduce file sizes by up to 90%.
Open Font SubsetterWritten & Verified by
Sarah Mitchell
Product Designer, Font Specialist
Font Subsetting FAQs
Common questions about subsetting fonts for performance
