font-display
font-display
Control how fonts load and display.
font-display Values
/* Swap: Show fallback immediately, swap when ready */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
}
/* Fallback: Show fallback, swap only if ready quickly */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: fallback;
}
/* Block: Hide text for up to 3 seconds */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: block;
}
/* Optional: Show fallback only */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: optional;
}
Recommended Usage
| Use Case | font-display |
|---|---|
| Body text | swap |
| Headings | swap or fallback |
| Icons | block |
| Critical UI | optional |
Implementation
/* Google Fonts example */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
/* Self-hosted */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-400.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF; /* Latin characters only */
}
Font Subsetting
Font Subsetting
Include only the characters you need to reduce file size.
Unicode Range
/* Latin characters */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-latin.woff2') format('woff2');
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F;
}
/* Greek characters */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-greek.woff2') format('woff2');
font-display: swap;
unicode-range: U+0370-03FF;
}
/* Cyrillic characters */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-cyrillic.woff2') format('woff2');
font-display: swap;
unicode-range: U+0400-04FF;
}
Generate Subsets
# Using pyftsubset
pip install fonttools brotli
pyftsubset input.ttf \
--output-file=output-latin.woff2 \
--flavor=woff2 \
--unicodes=U+0000-00FF
# Using Google Fonts API
https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap
Variable Fonts
/* Single file for all weights */
@font-face {
font-family: 'InterVariable';
src: url('/fonts/inter-variable.woff2') format('woff2-variations');
font-weight: 100 900;
font-display: swap;
}
/* Use variable weights */
body {
font-family: 'InterVariable';
font-weight: 400;
}
h1 {
font-weight: 700;
}
Size Comparison
| Format | Full Font | Latin Subset | Reduction |
|---|---|---|---|
| TTF | 500KB | 150KB | 70% |
| WOFF2 | 300KB | 90KB | 70% |
| Variable | 200KB | 60KB | 70% |
Font Preloading
Font Preloading
Preload critical fonts to prevent FOUT/FOIT.
HTML Preload
<!-- In <head> -->
<link
rel="preload"
href="/fonts/inter-400.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<link
rel="preload"
href="/fonts/inter-700.woff2"
as="font"
type="font/woff2"
crossorigin
/>
JavaScript Preloading
// Preload fonts
document.fonts.preload('/fonts/inter-400.woff2');
document.fonts.preload('/fonts/inter-700.woff2');
// Wait for fonts to load
await document.fonts.ready;
console.log('Fonts loaded');
Size-Adjust for Fallback
/* Match fallback font metrics to minimize CLS */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
/* Fallback font stack */
:root {
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
Critical Font Loading Strategy
<!-- Inline critical font CSS -->
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-400.woff2') format('woff2');
font-weight: 400;
font-display: swap;
unicode-range: U+0000-00FF;
}
</style>
<!-- Preload -->
<link rel="preload" href="/fonts/inter-400.woff2" as="font" type="font/woff2" crossorigin />
<!-- Load non-critical fonts async -->
<script>
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/fonts.css';
document.head.appendChild(link);
</script>
Font Loading Checklist
- Use font-display: swap or fallback
- Preload critical fonts
- Subset fonts for needed characters
- Use variable fonts when possible
- Match fallback font metrics
- Limit font weights (2-3 max)
- Self-host fonts for better caching
Practice Problems
Create a reusable React component implementing Font Optimization. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Font Optimization using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Font Optimization for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What does font-display: swap do?
2. What is font subsetting?
3. Why preload fonts?
4. What is the benefit of variable fonts?
5. What is size-adjust?
Flashcards
Question
What are the font-display values?
Click to reveal answer
Answer
auto, block, swap, fallback, optional - each controls how fonts load and display.
Question
What is font subsetting?
Click to reveal answer
Answer
Including only the characters needed to reduce font file size.
Question
Why use variable fonts?
Click to reveal answer
Answer
Single file for all weights/styles, reducing HTTP requests and total file size.
Question
What is size-adjust?
Click to reveal answer
Answer
A CSS property that adjusts fallback font metrics to match the custom font, reducing CLS.
Question
What is Font Optimization?
Click to reveal answer
Answer
Font Optimization is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.font-display: swap is best for most use cases
- 2.Font subsetting can reduce file size by 70%+
- 3.Variable fonts provide all weights in one file
- 4.Preload critical fonts to prevent FOUT/FOIT
- 5.Match fallback metrics to reduce CLS
Interview Tips
- •Explain the difference between font-display values
- •Discuss font subsetting and when to use it
- •Know how to prevent CLS from font loading
Cheat Sheet
Font Optimization Cheat Sheet
font-display
- swap: Show fallback, swap when ready
- fallback: Show fallback, swap if quick
- block: Hide text up to 3s
- optional: Show fallback only
Subsetting
- Use unicode-range for character subsets
- Variable fonts for all weights in one file
Preloading
<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin />
CLS Prevention
- Match fallback metrics with size-adjust
- Use font-display: swap
- Preload critical fonts