Web Font Performance: Preloading, Subsetting, and Reducing CLS
How loading full web font families destroys Core Web Vitals, and how font subsetting, WOFF2 compression, and font-display: swap eliminate Cumulative Layout Shift.
Live Interactive Demonstration
Try the principles discussed in this article directly on our live tool.
A single web font family with 4 weights (Regular, Medium, SemiBold, Bold) can easily weigh over 400KB if not optimized.
When a visitor lands on your website over mobile 4G, their browser encounters the dreaded FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text). When the custom font finally pops in, lines reflow, paragraphs jump, and your Google Cumulative Layout Shift (CLS) score plummets into the red.
Here is the engineering playbook to make custom web fonts load with zero layout shift.
1. Eliminate Layout Shift with size-adjust and Fallback Overrides
When custom web fonts load, their x-height and letter dimensions rarely match the fallback font (Arial or Times New Roman). When the custom font replaces the system fallback, content shifts vertically.
Modern CSS allows you to match fallback metrics to your custom font:
/* Define an adjusted fallback that matches Inter's physical footprint */
@font-face {
font-family: 'Inter-Fallback';
src: local('Arial');
ascent-override: 90%;
descent-override: 22.5%;
line-gap-override: 0%;
size-adjust: 107.5%;
}
body {
font-family: 'Inter', 'Inter-Fallback', sans-serif;
}
2. Font Subsetting: Why You Don’t Need 2,000 Unused Glyphs
A standard full Unicode font file contains glyphs for Cyrillic, Greek, mathematical symbols, arrows, and currency signs. If your application only serves English, Spanish, and French users, 80% of the font file is wasted bandwidth.
- Full Font File: ~120KB per weight
- Latin-Subsetted WOFF2: ~14KB per weight (an 88% reduction!)
<!-- Load only the Latin glyph subset from Google Fonts -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&subset=latin&display=swap"
/>
3. The Modern Font Loading Triad
<!-- 1. Preconnect to font CDN domains -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- 2. Preload the primary body Regular font weight -->
<link
rel="preload"
href="/fonts/inter-latin-400.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<!-- 3. Always use font-display: swap in CSS -->
<style>
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap; /* Immediately renders fallback, swaps smoothly */
}
</style>
Summary Checklist for 100/100 Core Web Vitals:
- Use WOFF2 exclusively (ignore legacy TTF/EOT).
- Subset your glyphs to the target audience languages.
- Preload only the single most critical font weight (e.g., Body Regular).
- Use
font-display: swapto prevent Flash of Invisible Text.
More from the IpsumForge Engineering Blog
Bidirectional (RTL/LTR) Layout Survival Guide for Frontend Engineers
Master CSS Logical Properties, flexbox auto-mirroring, and directional icon flipping to support Arabic, Hebrew, and Persian without writing duplicate stylesheets.
CSS clamp() and Modern Fluid Typography: No More Media Query Bloat
How to eliminate dozens of rigid media queries and implement seamless fluid typography across mobile, tablet, and desktop viewports using modern CSS clamp().