Font Subsets and unicode-range: Load Only the Glyphs a Page Needs
Learn what a subset changes, what unicode-range tells the browser, and how to test multilingual font delivery safely.
A web font can be visually right and still cost too much to deliver. This is especially clear with families that cover many writing systems: one file may contain far more glyphs than a single route uses. Subsetting produces a smaller font resource with selected character coverage. CSS unicode-range is different: it describes which code points a declared face can serve and helps the browser decide whether the face matches text on the page.
A Subset and a Range Are Different
A subset is a font file built with selected glyphs. A unicode-range descriptor is metadata in an @font-face rule. The descriptor does not remove characters from a file or create a smaller resource. The stylesheet can declare several faces under the same family name with different ranges, and a browser can select a face when text needs characters in its range. The file and declaration have to describe compatible coverage.
The distinction matters when debugging missing glyphs. If a character is absent from a WOFF2 file, adding its code point to unicode-range cannot make it appear. If ranges overlap, font matching also depends on style, weight, ordering, and whether a glyph exists in the resource. Keep the subset process and CSS declarations in sync, and inspect network requests to see which resources the route actually transfers.
Partition by Real Content
A Latin-heavy page might use a Latin subset plus the punctuation and combining marks it needs, while a Japanese article may require a much broader CJK resource. These are not universal partitions. Localized names contain exceptions, languages use different characters, and the selected font's character map determines the glyphs it can render. Prefer documented subsets from the font provider or a build step based on real site content over ranges copied from memory.
Complex scripts add another reason to keep a tested pipeline. Shaping can depend on neighboring characters, combining marks, and OpenType tables beyond a simple one-code-point-to-one-glyph mapping. A subset tool that removes a character that looks unused may break a localized word or mark sequence. Use a shaping-aware tool and render representative words from every supported language before publishing generated files.
A stylesheet declares a broad range for a resource that does not contain the needed character; the browser still falls back for that glyph.
Each file contains intended glyph coverage, and its @font-face range describes that same coverage.
Inspect both the font's character map and the network response; neither check replaces the other.
A Two-Resource Illustration
@font-face {
font-family: 'Local UI';
src: url('/fonts/local-ui-latin.woff2') format('woff2');
font-weight: 400;
font-display: swap;
unicode-range: U+0000-00FF, U+0100-024F, U+0300-036F;
}
@font-face {
font-family: 'Local UI';
src: url('/fonts/local-ui-kana.woff2') format('woff2');
font-weight: 400;
font-display: swap;
unicode-range: U+3040-30FF;
}These demonstration ranges are not a complete Japanese subset. Verify file coverage, punctuation, marks, Han characters, and fallback behavior for your real content.
The second rule does not claim that kana is all a Japanese page needs. A real article may contain Han characters, full-width punctuation, Latin product names, and supplementary ideographs. Production ranges should come from the font package or a reproducible subset manifest, not from copying this short example as a complete language solution.
Variable fonts need the same accounting. A variable file can expose a range of weights or other axes, but its character coverage and transfer size are properties of that resource. A provider's CSS API may build responses from requested axes and subsets, while a self-hosted file is only as selective as the file you generate. Compare compressed transfer size and the network waterfall rather than assuming that a variable font or range descriptor is automatically smaller.
Check the Browser's Match
Test both warm and cold caches. Render the route in every supported locale, inspect missing-glyph boxes, and disable the custom font to see whether fallback remains acceptable. Network tools show which resources were requested; font inspection tools show which characters and axes exist inside the files. A fallback stack ensures that a missing or late resource does not leave a blank text region.
- Generate subsets from real routes and localization content.
- Keep each unicode-range aligned with the corresponding file's glyph coverage.
- Retain marks, punctuation, and script sequences real words need.
- Check requests, transfer sizes, missing glyphs, and fallback rendering.
- Rebuild and retest when content or supported languages change.
Subsetting is a measurable optimization, not a contest to produce the smallest possible font. A reliable subset covers what the site publishes while preserving shaping and fallback. Start from observed requests and supported languages, automate derivation where possible, then verify rendered words. A few extra kilobytes are preferable to a localized name that appears as tofu or a sequence whose marks no longer shape correctly.