Back to Blog
PerformanceJuly 9, 20264 min read

Font-display swap and Critical Font Optimization for LCP

Learn how to use font-display swap and critical font optimization to stop FOIT and FOUT, effectively boosting LCP and INP performance on your site.

web performancefont loadingcsslcpinpclsfrontendPerformanceWeb Vitals

Mastering Web Performance Font Loading

I spent most of last week debugging a stubborn layout shift issue on a client’s dashboard. The text would jump about 12 pixels downward the moment the custom brand font finished downloading, triggering a massive spike in Cumulative Layout Shift (CLS) and tanking the Interaction to Next Paint (INP) score. We’d been loading our fonts via a standard @font-face declaration, assuming the browser would handle it gracefully. It didn't.

If you’re seeing similar behavior, you aren't alone. Unoptimized typography is one of the most common silent killers of Core Web Vitals. When a browser pauses rendering to wait for a font file, you get a "Flash of Invisible Text" (FOIT). When it renders a fallback font and then swaps it, you get a "Flash of Unstyled Text" (FOUT) and that dreaded layout shift.

Why Font-Display Swap Matters

The most immediate fix for FOIT is the font-display: swap property. It tells the browser to use a system font immediately while the custom font downloads in the background.

CSS
@#9CDCFE">color:#4EC9B0">font-face {
  #9CDCFE">font-family: 'Inter';
  #9CDCFE">src: url('/fonts/inter.woff2') format('woff2');
  #9CDCFE">font-display: swap;
}

By using swap, you ensure the text is visible to the user as quickly as possible. This is a massive win for your Largest Contentful Paint (LCP) if your hero section relies on text. However, swap doesn't solve the layout shift caused by the font swap itself. If the fallback font (like Arial) has different metrics than your custom font, the text block will resize when the swap happens.

Strategies for FOIT FOUT Prevention

To truly fix the layout shift, you need to match the fallback font dimensions to your primary font. We’ve had success using size-adjust and ascent-override in modern CSS.

  1. Identify the Fallback Metrics: Use a tool to compare the x-height and line height of your web font against standard system fonts.
  2. Override Fallback Styles: Create a "fake" font face for your fallback that mimics the primary font's dimensions.
CSS
@#9CDCFE">color:#4EC9B0">font-face {
  #9CDCFE">font-family: 'Inter-Fallback';
  #9CDCFE">src: local('Arial');
  #9CDCFE">size-adjust: 95%;
  #9CDCFE">ascent-override: 90%;
}

This ensures that when the browser swaps the fonts, the layout remains rock-solid. It’s a bit of extra configuration, but it’s the only way to get a perfectly stable layout while still using custom typography. For deeper dives into debugging these rendering pipelines, check out my guide on Optimizing Forced Synchronous Layout: A Guide to Better INP.

Implementing Critical Font Optimization

If your font is critical for the LCP element, don't wait for the CSS file to download before fetching it. Use a <link rel="preload"> tag in your <head> to start the download immediately.

StrategyBest ForImpact
font-display: swapGeneral textEliminates FOIT, reduces LCP latency
rel="preload"Hero/LCP fontsReduces time-to-first-render for fonts
size-adjustCLS reductionPrevents layout shifts during swap

While preloading is great, be careful. Preloading too many fonts can compete with your main JS and CSS bundles for bandwidth. Only preload the specific weights and styles you need for the "above-the-fold" content. We've previously discussed how to use Fetchpriority vs. Preload: Optimizing LCP and INP Performance to keep these priorities balanced.

What I’d Do Differently

Next time I tackle this, I’m going to start with variable fonts from day one. Variable fonts allow you to ship a single file for multiple weights and styles, which significantly reduces the number of network requests and improves overall load time. Managing five separate .woff2 files is a recipe for performance degradation.

If you are struggling with these metrics, consider looking into Web Performance: Stop Layout Shifts with Smarter Font Loading to see how we handle these issues at scale.

Frequently Asked Questions

Does font-display: swap hurt my CLS? It can. If your fallback font is visually different from your custom font, the swap will cause a layout shift. Use size-adjust to match their dimensions.

Should I preload every font file? No. Only preload the fonts required for your LCP element or critical UI components. Over-preloading can block more important assets.

What is the difference between FOIT and FOUT? FOIT (Flash of Invisible Text) happens when the browser hides text until the font loads. FOUT (Flash of Unstyled Text) happens when the browser shows the fallback font and then swaps it for the custom font later.

Optimization is an iterative process. Keep measuring your LCP and INP in the field—lab data is great, but real user experience is the only metric that truly reflects how your users interact with your site.

Similar Posts