Mastering font-display for CLS and Perceived Performance
When a browser loads a web font, there is a brief moment where the font file hasn't arrived yet, but the text content is ready to be painted. The font-display CSS property tells the browser how to handle this "limbo" state.
Choosing the right value is critical for Cumulative Layout Shift (CLS) and First Contentful Paint (FCP).
1. The Values Explained
font-display: block (The Default)
- Behavior: The text is invisible (transparent) for up to 3 seconds while waiting for the font. If it loads, it swaps. If not, it shows the fallback.
- Pros: No "Flash of Unstyled Text" (FOUT).
- Cons: "Flash of Invisible Text" (FOIT). Users see a blank screen. Bad for PageSpeed.
- Use Case: Icon fonts (FontAwesome) where a fallback character would look broken.
font-display: swap (The Standard Recommendation)
- Behavior: The browser shows the fallback font (e.g., Arial) immediately. Once the web font loads, it swaps it in.
- Pros: Text is readable instantly (Great FCP).
- Cons: The swap causes a visual "jump" or re-flow (CLS) if the custom font is wider/narrower than Arial.
- Use Case: Body text, headings, and most content.
font-display: optional (The CLS Killer)
- Behavior: The browser gives the font a very short window (100ms) to load. If it's not there, it uses the fallback font and never swaps. The custom font is downloaded in the background and used on the next page view.
- Pros: Zero Layout Shift. The text never changes shape after the first paint.
- Cons: First-time visitors might see Arial instead of your brand font.
- Use Case: Critical optimization for mobile devices on slow networks where layout stability is more important than branding.
2. Reducing CLS with swap
If you use swap (which most sites do), you must minimize the layout shift caused by the font switching.
The Problem
Your custom font "Inter" might be 10% wider than "sans-serif" (Arial). When the swap happens, a paragraph might jump from 3 lines to 4 lines, pushing everything down.
The Solution: Metric Overrides
In 2026, CSS allows you to tweak the fallback font to match the dimensions of your web font using ascent-override, descent-override, and size-adjust.
/* 1. Define the Web Font */
@font-face {
font-family: 'MyBrandFont';
src: url('my-brand-font.woff2') format('woff2');
font-display: swap;
}
/* 2. Define a Tuned Fallback */
@font-face {
font-family: 'MyBrandFallback';
src: local('Arial'); /* Use a system font */
/* Adjust these numbers until it matches MyBrandFont exactly */
ascent-override: 90%;
descent-override: 20%;
size-adjust: 95%;
}
/* 3. Use the Stack */
body {
font-family: 'MyBrandFont', 'MyBrandFallback', sans-serif;
}
Tip: Use tools like the "Font Style Matcher" or Chrome DevTools to find the exact percentage values.
3. Summary Strategy
- Icons: Always use
font-display: block. - Body Text: Use
font-display: swapcombined with Metric Overrides to prevent the jump. - Extreme Performance: Use
font-display: optionalif you are failing Core Web Vitals solely due to font shifts and can't get overrides to work perfectly.