Web Font Loading Strategy
Also Known As
FOIT
FOUT
font-display
font loading
web fonts
TL;DR
Controlling how custom fonts load to avoid FOIT (invisible text), FOUT (flash of unstyled text), and layout shift — using font-display, preloading, and system font stacks.
Explanation
Font loading problems: FOIT (Flash of Invisible Text) — browser hides text while font downloads; FOUT (Flash of Unstyled Text) — fallback font shown then swaps; CLS (Cumulative Layout Shift) — font metric difference causes layout reflow. Solutions: font-display: swap (show fallback immediately, swap when loaded — eliminates FOIT but allows FOUT), font-display: optional (use font only if already cached), preloading critical fonts (<link rel=preload as=font>), font subsetting (only include used characters), self-hosting (avoids external DNS lookup), and size-adjust + ascent-override to match fallback font metrics (eliminates CLS).
Common Misconception
✗ font-display: swap always improves user experience — swap eliminates FOIT but causes FOUT and potentially significant CLS if fallback and web font have very different metrics; font-display: optional may give better UX for secondary fonts.
Why It Matters
FOIT causes text to be invisible for 1-3 seconds on slow connections — font-display: swap shows text immediately while the web font loads in the background.
Common Mistakes
- Not preloading critical fonts — they are discovered late in the render pipeline.
- Loading all weights and variants — load only the weights/styles actually used.
- Google Fonts without self-hosting — extra DNS lookup + connection adds 100-400ms latency.
- No fallback font metrics adjustment — causes layout shift when web font loads.
Code Examples
✗ Vulnerable
/* Loading fonts without display strategy — FOIT:
@font-face {
font-family: 'MyFont';
src: url('font.woff2');
/* No font-display — browser hides text for 3 seconds */
}
/* Slow connection: 3-second invisible text */
✓ Fixed
/* Optimised font loading: */
@font-face {
font-family: 'MyFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* Show fallback immediately */
unicode-range: U+0000-00FF; /* Subset: Latin only */
}
/* Match fallback metrics to minimise CLS: */
@font-face {
font-family: 'MyFont-fallback';
src: local('Arial');
size-adjust: 104%; /* Match web font's cap height */
ascent-override: 95%;
}
body { font-family: 'MyFont', 'MyFont-fallback', sans-serif; }
<!-- Preload critical font: -->
<link rel="preload" href="/fonts/myfont.woff2" as="font" type="font/woff2" crossorigin>
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
16 Mar 2026
Edited
22 Mar 2026
Views
46
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 14
Google 10
Perplexity 8
Unknown AI 2
Ahrefs 2
SEMrush 2
ChatGPT 2
Meta AI 1
Majestic 1
Also referenced
How they use it
crawler 38
crawler_json 3
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟡 Medium
⚙ Fix effort: Low
⚡ Quick Fix
Add font-display: swap to @font-face rules; preload the most critical font file; self-host fonts instead of loading from Google Fonts to eliminate extra DNS lookup
📦 Applies To
css CSS3
web
🔗 Prerequisites
🔍 Detection Hints
Google Fonts @import in CSS blocking render; no font-display: swap; no preload on above-fold font; FOIT flash of invisible text
Auto-detectable:
✓ Yes
lighthouse
pagespeed-insights
webfont-loader
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Low
✓ Auto-fixable
Fix: Low
Context: File