If you’ve ever seen a website where the text suddenly ‘jumps’ or changes style a second after the page loads, you’ve witnessed the struggle of font rendering. When that text is part of your hero section, it directly impacts your Largest Contentful Paint (LCP). In my experience, optimizing font loading for LCP is often the ‘missing link’ for developers who have already optimized their images and server response times but are still seeing mediocre Core Web Vitals scores.

When a browser encounters a custom font, it has to decide whether to show a fallback font first (Flash of Unstyled Text – FOUT) or hide the text until the font arrives (Flash of Invisible Text – FOIT). Both are detrimental to UX, but FOIT is a silent LCP killer because the browser doesn’t consider ‘invisible’ text as painted. If you are wondering why is my LCP so high, your font loading strategy is a prime suspect.

10 Tips for Optimizing Font Loading for LCP

1. Self-Host Your Fonts

While Google Fonts is convenient, it introduces an extra DNS lookup and TCP connection to a third-party domain. I always recommend self-hosting. By serving fonts from your own domain, you can utilize HTTP/2 multiplexing, meaning the browser can request the font over the same connection used for your HTML and CSS.

2. Use font-display: swap

This is the single most effective CSS property for LCP. By adding font-display: swap; to your @font-face declaration, you tell the browser to show the fallback system font immediately and swap it once the custom font has downloaded.

@font-face {
  font-family: 'BrandFont';
  src: url('/fonts/brandfont.woff2') format('woff2');
  font-display: swap;
}

3. Preload Critical Fonts

If your LCP element is a H1 tag using a custom font, don’t wait for the CSS to be parsed to start the font download. Use a preload link in your HTML <head>. This moves the font to the top of the network priority queue.

<link rel="preload" href="/fonts/brandfont.woff2" as="font" type="font/woff2" crossorigin>

4. Stick to WOFF2

Stop using TTF or OTF for web delivery. WOFF2 uses Brotli compression and is significantly smaller. In my testing, switching from WOFF to WOFF2 reduced font payload sizes by nearly 30%, which directly shaved milliseconds off the LCP.

5. Subset Your Fonts

Most fonts include characters for languages you’ll never use. Use tools like pyftsubset to create a ‘subset’ containing only the Latin characters needed for your site. A 150KB font file can often be reduced to 20KB without any visible difference to the user.

6. Match Fallback Metrics

The ‘jump’ during a font swap happens because the fallback font (like Arial) has different dimensions than your custom font. To fix this, use the size-adjust property in your CSS to make the fallback font occupy the same space as the custom one, reducing Layout Shift (CLS) and stabilizing LCP.

@font-face {
  font-family: 'BrandFont-Fallback';
  src: local('Arial');
  size-adjust: 92%;
  ascent-override: 90%;
}

7. Use Variable Fonts

Instead of loading four different files for Regular, Italic, Bold, and Bold-Italic, use one single Variable Font file. This reduces the number of HTTP requests and the overall byte size, which is a core part of any core web vitals optimization guide 2026.

8. Avoid @import in CSS

Using @import inside a CSS file creates a sequential chain: HTML → CSS → Font. This delays the font discovery. Always use <link> tags in the HTML head to allow the browser to discover resources in parallel.

9. Leverage Cache-Control

Fonts rarely change. Set your Cache-Control header to public, max-age=31536000, immutable. This ensures that once a user visits one page, the font is cached locally for a year, making subsequent page loads nearly instantaneous.

10. Audit with the Network Tab

I always verify my results using the Chrome DevTools Network tab. Filter by ‘Font’ and check the ‘Waterfall’ column. If you see a large gap before the font begins downloading, your preloading strategy needs work.

As shown in the image below, seeing the relationship between the CSS request and the Font request is key to identifying bottlenecks.

Chrome DevTools Network tab showing the waterfall sequence of CSS and Font loading
Chrome DevTools Network tab showing the waterfall sequence of CSS and Font loading

Common Mistakes I See

Measuring Success

To see if your changes worked, don’t just rely on a single PageSpeed Insights run. Use the Lighthouse User Flows or Web Vitals extension. Specifically, look for the ‘Largest Contentful Paint element’ in the report; if it’s a text block, check if the ‘Render Blocking Resources’ list still includes your fonts.

Pro Tip: If you’re using Next.js, use next/font. It automatically handles self-hosting, subsetting, and zero-layout-shift by generating the optimal fallback CSS for you.

Ready to dive deeper into performance? Check out our full core web vitals optimization guide 2026 for a holistic approach to speed.