In web development, every millisecond on the critical path matters. Typography is part of your visual identity, yet a single self-hosted family can add hundreds of kilobytes before the browser paints the hero line clients actually see. That cost often shows up as slower First Contentful Paint (FCP) and a worse Largest Contentful Paint (LCP) when the LCP element is a headline set in a custom face.
Font subsetting is the practical fix: ship only the characters (glyphs) each page or component needs instead of entire typefaces built for every language and symbol you will never render.
What font subsetting is
A typical desktop font file contains thousands of glyphs: Latin extended, Cyrillic, ligatures, numerals, punctuation, and symbols you may never use on a marketing site. When you @font-face that file or pull it from a CDN, the browser still has to download and parse the whole package unless you split it.
Subsetting creates a smaller font file that includes a defined subset of Unicode code points. Examples:
- A display font used only on one H1 might need fewer than 40 characters.
- A Latin-only blog body font does not need CJK tables on every article.
- UI labels in English can omit unused weights and scripts.
The browser downloads less data, spends less time decoding, and can apply the face sooner. You keep the look; you drop the dead weight.
When font subsetting improves web font performance and LCP
Subsetting pays off fastest in these cases:
| Situation | Why subsetting helps |
|---|---|
| Display or hero typography | Few unique characters, high visual impact, often on the LCP text node |
| Single-language sites | Remove unused scripts and diacritic ranges you do not publish |
| Icon or logo fonts misused as full fonts | Replace with SVG where possible; subset if you must keep a font icon set |
| Multiple weights loaded globally | Subset per weight, or load weights only on routes that need them |
It is lower priority when you already use a system font stack for body copy and only load one small variable font with modern compression. Still measure: “small” on disk is not always small on a slow mobile connection.
Pair subsetting with loading discipline: font-display: swap or optional, preload only the file that blocks the hero, and avoid loading six weights site-wide because the brand guide lists them. Our image optimisation strategies for better LCP guide covers the image side of the same paint problem; fonts are the other half of many hero templates.
Font subsetting example: hero display copy without the full font file
Imagine a campaign landing page with one H1 in a distinctive display face: “Summer sale ends Sunday”. The full commercial font might be 180 KB of WOFF2 per weight. The string uses letters, a space, and basic punctuation: perhaps 28 glyphs.
Subsetting to those glyphs (plus a few extras you reserve for CMS edits, such as 0123456789 and -%) might produce a file under 15 KB. Same aesthetics on the title; far less work for the network and font loader on first visit.
Always keep a slightly wider subset than the literal string if editors can change copy without redeploying. A common pattern is “characters used on site” plus a safety buffer of numerals and common punctuation, or a per-locale subset file.
Four tools for font subsetting
You do not need to hand-edit binary tables for most projects. These four tools cover the usual workflows.
Google Fonts
Google Fonts hosts families with many axes and scripts. When you embed through the Google Fonts CSS API, you can limit what Google serves:
- Use the
text=parameter to request only the characters in a string (useful for fixed hero copy). - Choose only the weights and styles you need in the embed code generator.
- Prefer
display=swap(oroptionalwhere appropriate) so text stays visible while the file loads.
Self-hosting a Google Font download is also valid: download the family, subset locally, and serve WOFF2 from your own CDN for stricter cache control.
Font Squirrel Webfont Generator
Font Squirrel’s Webfont Generator is the familiar upload-and-convert workflow. Upload your source (check your licence allows web embedding), choose “Expert” mode, and define custom subsets: Unicode ranges, specific glyphs, or language presets. It outputs WOFF2/WOFF kits with a starter @font-face block.
Good for agency teams without a font toolchain in CI: one-off subsets for a client launch, then store the outputs in the repo or asset pipeline.
Everything Fonts Subsetter
Everything Fonts Subsetter accepts uploaded TTF/OTF/WOFF files and builds a reduced file from the characters you paste or select. Useful when you already know the exact glyph list from a design export or when you are trimming an existing self-hosted file after an audit.
FontForge
FontForge is desktop software for creating and editing fonts. Use it when you need precise control: merge subsets, remove tables, or build a custom subset for a product name baked into a brand face. The learning curve is steeper than a web generator, but it is the right tool when the font is yours to modify or when legal subsetting must be documented for the client.
How to implement font subsets (@font-face, unicode-range, font-display)
After you have a smaller file, wire it so the browser does not download the old full font by mistake.
@font-face {
font-family: "Brand Display";
src: url("/fonts/brand-display-hero-subset.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
unicode-range: U+0020-007F;
}
unicode-range tells the browser to skip downloading this file for characters outside the range. You can split one family into multiple files (Latin hero, Latin body, numerals-only) so each page loads only what it needs.
For variable fonts, subsetting is trickier but still worthwhile on high-traffic templates. Test on real devices: some older browsers handle unicode-range plus variable fonts differently than a static WOFF2 subset.
Document subsets in your client handover: which file applies to which template, and how to regenerate when marketing changes the hero string.
Reduce font file size: less data per page view
Subsetting is a technical optimisation first. Smaller font files mean less data over the wire per page view. On a site with 50 000 monthly sessions and a 150 KB font removed from the critical path, you avoid gigabytes of transfer over a year without changing the design.
That matters for:
- Mobile users on metered or weak connections
- CDN and origin egress costs at scale
- Battery and CPU spent decoding fonts that never render
We avoid treating that as vague “eco” marketing. The measurable claim is simpler: you sent fewer bytes for the same page. If sustainability reporting matters to your client, subsetting is one line item next to image compression and script audits.
How to verify LCP and FCP after font subsetting
Subsetting is not done when the file size looks smaller in Finder. Verify in the browser and in your monitoring rhythm.
- Network panel: Confirm the subset WOFF2 is requested (not the legacy full file). Check transfer size and that the request sits early enough for the hero.
- PageSpeed Insights or Lighthouse: Compare FCP and LCP before and after on the same URL and throttling profile. Lab scores move for many reasons; keep one change per deploy when you are proving cause.
-
Filmstrip or trace: Ensure the hero text does not flash invisible for long periods. If
font-display: swapcauses a large layout shift when the custom face arrives, fix CLS separately (reserved space, fallback metrics). - Production monitoring: If you run automated PageSpeed monitoring, add the template to a performance budget so a future CMS or plugin change does not reintroduce the full font on every page.
Agencies maintaining many sites benefit from the same loop as images: fix the asset, prove it in lab, then watch scheduled tests so the regression does not return quietly on the next theme update.
Pick one high-traffic URL where the LCP node is text in a custom font. List the characters that can appear in that block (or export copy from the CMS). Generate a subset with Font Squirrel or Everything Fonts, deploy with font-display: swap, and re-run PSI. If LCP improves, roll the same pattern to other display templates and document the glyph list for the client.
Common font subsetting mistakes
- Subsetting too aggressively so editors cannot type an em dash or an accented character without tofu squares.
- Loading both subset and full font because an old enqueue line was left in WordPress or the tag manager.
- Subsetting body fonts but still loading five weights on pages that use one weight.
- Ignoring licensing; not every foundry permits subsetting or self-hosting. Read the EULA before Font Squirrel or FontForge exports go to production.
-
Skipping fallbacks; use a similar system stack in
font-familyso text stays readable if the subset fails to load.
Typography should not be the reason a fast layout scores poorly on paint metrics. Subsetting keeps the brand face while respecting the budget the network actually has.
Create a free account to track LCP and FCP across client sites with scheduled PageSpeed tests and performance budgets.
FAQ
Does font subsetting affect SEO?
Not directly. Search engines care about experience signals and crawlability. Faster paint and stable layout support the page experience story; subsetting is one input, not a ranking lever on its own.
Can I subset Google Fonts without self-hosting?
Yes, partially. The CSS API text= and family/axis parameters reduce what Google sends. For maximum control and caching, download and self-host a subset you generated.
Will subsetting break translations?
It can if you subset for English only and later add a Greek or Japanese locale. Plan per-locale subset files or a wider subset for multilingual templates.
WOFF2 only, or still ship WOFF?
For modern browsers in 2026, WOFF2 alone is usually enough. Keep WOFF only if you must support legacy clients named in the client’s browser support policy.
How does subsetting compare to using a system font stack?
System fonts add zero webfont bytes. Subsetting is the middle path when brand guidelines require a custom face but you refuse to ship an entire foundry file on every route.
Should I subset icon fonts?
Prefer SVG icons. If you remain on an icon font, subset to the icons in use or migrate to inline SVG to remove font decoding from the critical path entirely.
Top comments (0)