Back to Blog
PerformanceJuly 4, 20263 min read

Web Performance: Stop Layout Shifts with Smarter Font Loading

Web Performance is often killed by font loading. Learn how to stop layout shifts (CLS) and FOIT using priority hints and font metadata for faster rendering.

web-performancecore-web-vitalsclsfont-loadingcssweb-fontsPerformanceWeb VitalsFrontend

When I first started auditing our site's metrics, I noticed a recurring, frustrating spike in our Cumulative Layout Shift (CLS). The culprit wasn't a rogue ad script or a slow image; it was a 60kb web font file that decided to swap in right as the user started reading the hero section.

Improving Web Performance isn't just about shaving milliseconds off your server response; it’s about how the browser constructs the page. If you're struggling with fonts jumping around, you’re likely dealing with FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text). Both are death to your user experience and, consequently, your Core Web Vitals.

The Wrong Turn: Preloading Everything

My first instinct was to preload every font file in the <head>. It seemed logical: tell the browser to grab them immediately. I added <link rel="preload"> for four different weights.

The result? I accidentally created a massive bottleneck. By preloading every weight, I forced the browser to compete for bandwidth during the critical initial paint. My LCP (Largest Contentful Paint) actually got worse by around 150ms because the browser was busy downloading a "bold-italic" font that wasn't even used above the fold.

I learned the hard way that you should only preload fonts that are strictly necessary for the initial viewport. If you're interested in digging deeper into how to balance these requests, check out our guide on Core Web Vitals Optimization: Mastering Resource Hints and Fetch Priority.

Architecting for Stability: Font Metadata and CSS

To fix the layout shifts, you need to match your fallback system font to your web font as closely as possible. If you don't, the browser will swap the system font for the web font, and the line lengths will change, pushing content down the page.

Using size-adjust and ascent-override in your @font-face declaration is a game changer. It allows you to tweak the fallback font's metrics so the transition is invisible.

CSS
@#9CDCFE">color:#4EC9B0">font-face {
  #9CDCFE">font-family: 'MyFont-Fallback';
  #9CDCFE">src: local('Arial');
  #9CDCFE">size-adjust: 95%;
  #9CDCFE">ascent-override: 90%;
}

By fine-tuning these properties, you keep the text footprint identical during the transition. For more on how to use these CSS properties to stop UI jitter, see my previous post on Eliminating Cumulative Layout Shift: A Practical Guide to CLS Optimization.

Using Priority Hints to Control Loading

Once you've stabilized your layout, you need to control when the fonts load. fetchpriority is your best friend here. If a font is critical for the hero section, mark it as high priority. If it's for a footer or a secondary section, let it load later.

StrategyImpact on CLSImpact on LCP
No OptimizationHighMedium
Global PreloadMediumLow
Priority HintsLowHigh
Font Metrics OverrideVery LowNeutral

Applying fetchpriority="high" to your preloads ensures the browser prioritizes those specific files over lower-priority assets like tracking scripts. It’s a surgical way to ensure your Font Loading strategy actually helps the user, rather than fighting against them.

When to use what?

If you're still seeing issues with FOIT, you might want to revisit your Font Loading Strategy: Eliminate FOIT and Layout Shifts. Sometimes the best solution isn't a technical hack but a design decision to use system fonts for body text and only load web fonts for specific headers.

Final Thoughts

I'm still experimenting with font-display: swap vs. font-display: block. In some cases, swap causes a jarring layout shift that triggers a penalty in CLS scores, even if it technically gets the text on the screen faster. I've found that combining font-display: swap with size-adjust is the sweet spot, but it requires a lot of manual testing for every font family.

What I’d do differently next time? I’d start by auditing the font usage on mobile devices specifically. We often optimize for desktop and forget that mobile networks are where these layout shifts are most punishing. Don’t assume your font strategy works everywhere just because your local machine renders it perfectly.

Similar Posts