Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
PerformanceJune 21, 20264 min read

Font Loading Strategy: Eliminate FOIT and Layout Shifts

Stop layout shifts and FOIT by mastering your font loading strategy. Learn how to optimize web performance and Core Web Vitals with CSS and preload tips.

web performancefontscssfrontendweb developmentcore web vitalsoptimizationPerformanceWeb Vitals

I spent three days last month chasing a "ghost" layout shift that only appeared on mobile devices under 4G throttled conditions. It turned out our custom typography wasn't just slow—it was triggering a massive re-flow the second the woff2 files finished downloading.

If you’ve ever watched a page jump while the text suddenly snaps from a system sans-serif to your brand font, you’ve experienced the Flash of Unstyled Text (FOUT) or the more jarring Flash of Invisible Text (FOIT). These aren't just aesthetic annoyances; they are direct hits to your Cumulative Layout Shift: Advanced Strategies to Stop UI Jitter score and general web performance.

The Problem with Default Font Loading

Browsers are notoriously conservative with fonts. By default, most browsers hide text until the font file is fully downloaded, leading to FOIT. This is a nightmare for Core Web Vitals, specifically your Largest Contentful Paint (LCP) and visual stability metrics.

We initially tried wrapping our font declarations in a standard @font-face block without any specific display swap logic. It felt clean, but it caused the browser to hang for roughly 400ms on a cold cache, leaving the user staring at a blank screen.

Choosing the Right Font Loading Strategy

To fix this, we need to move away from the browser's default behavior and take control of the rendering pipeline. The most effective font-display values are swap and optional.

  • font-display: swap: This is the industry standard. It tells the browser to use a system font immediately and swap in the custom font as soon as it's ready. It eliminates FOIT, but it’s the primary culprit for layout shifts if the fallback font doesn't match the dimensions of the custom font.
  • font-display: optional: This is safer for performance. It gives the font a tiny window (usually 100ms) to load. If it fails, the browser sticks with the system font for that navigation. It’s perfect for non-critical brand fonts.

Implementing Font Preloading

If your custom font is critical to the hero section, don't wait for the CSS parser to find it. Use a preload hint in your document head to kick off the download before the CSS is even parsed.

HTML
style="color:#808080"><style="color:#4EC9B0">link rel="preload" href="/fonts/brand-font.woff2" as="font" type="font/woff2" crossorigin>

Be careful with this, though. Preloading too many fonts will fight for bandwidth with your hero image and critical JavaScript, potentially hurting your INP Optimization: Strategies to Reduce Input Delay and Long Tasks metrics by bloating the main thread with network tasks.

Mitigating Layout Shifts

Even with the right font-display value, you’ll likely see layout shifts if your fallback font (e.g., Arial or Times New Roman) has different metrics than your custom font. The text will "jump" when the swap occurs.

We solved this by using size-adjust and ascent-override in our CSS. These properties allow you to force the fallback font to mimic the physical dimensions of your custom font.

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

By tweaking these, we got our layout shift down from 0.18 to about 0.02. It’s not pixel-perfect, but it’s close enough that the human eye doesn't perceive the jump during the swap.

What I Learned (and What I'd Do Differently)

If I were starting this project today, I’d prioritize variable fonts. Instead of loading four separate files (regular, bold, italic, bold-italic), a single variable font file covers all variations. It reduces the number of HTTP requests and simplifies your font-face declarations significantly.

Also, don't underestimate the power of system fonts. We ended up moving our "secondary" UI elements entirely to a system font stack. It’s faster, it’s native, and it looks consistent across OS platforms.

Frequently Asked Questions

Does preloading fonts hurt my LCP? It can if you preload too many. If you preload non-critical fonts, you’re stealing bandwidth from your LCP image. Only preload the fonts used in the "above-the-fold" content.

Is font-display: swap always the best choice? Not always. For body text, yes. For headings, you might prefer font-display: block if the layout is highly sensitive to font size changes, though you should pair that with aggressive preloading to avoid long blank screens.

How do I measure the impact of my font loading strategy? Use the Chrome DevTools "Network" tab to throttle your connection to "Fast 3G." Look at the "Waterfall" view to see when the font actually arrives and if it's causing a re-paint or layout shift.

Optimizing your fonts isn't a one-time fix. It’s a constant tug-of-war between design fidelity and performance. Keep your font files small, use swap where it makes sense, and always, always use size-adjust to minimize those annoying layout shifts.

Back to Blog

Similar Posts

A smooth abstract satin ribbon with curves set against a dark black background.
PerformanceJune 21, 20264 min read

Critical Rendering Path: Master Above-the-Fold Optimization

Optimize your critical rendering path to boost web performance metrics. Learn to eliminate render-blocking resources and prioritize above-the-fold content today.

Read more
PerformanceJune 21, 2026
4 min read

Cumulative Layout Shift: Advanced Strategies to Stop UI Jitter

Cumulative Layout Shift (CLS) ruins user experience. Learn how to stop UI jitter using CSS containment and aspect-ratio properties for a stable interface.

Read more
PerformanceJune 21, 20264 min read

Service Workers: Implementing Stale-While-Revalidate for Web Performance

Service Workers and stale-while-revalidate strategies help you achieve offline-first performance. Learn how to master the Cache API for instant loading.

Read more