Site speed

Fonts are slowing your site: how to load them right

TS Talha Shahzad··6 min read
The short version
  • Loading unused font weights adds 200-400 KB of invisible page weight on every load.
  • Most sites only use 2-3 font weights across all their pages.
  • font-display: swap prevents invisible text while custom fonts load.
  • Self-hosting and preloading critical fonts gives you the most control over loading behavior.

Fonts are one of the most overlooked speed problems on the web. Nobody thinks of their typeface as a performance issue. But when a site loads six font weights across every page, and the actual design only uses two of them, that is 200-400 KB of dead weight on every single page load.

I see this on nearly every site audit I run. A designer picks a beautiful typeface, the builder enables every available weight "just in case," and the CMS dutifully loads all of them on every page. Regular, medium, semibold, bold, italic, bold italic. Each weight is a separate file download. Each one delays rendering. And on most pages, only regular and bold are actually used in the CSS.

The real cost of unused font weights

A single font weight file is typically 30-80 KB (for WOFF2 format, which is the standard). Loading six weights means 180-480 KB of font files per page. That adds up:

  • Additional network requests that compete with critical resources
  • Delayed initial render while the browser downloads fonts it may never use
  • CLS (Cumulative Layout Shift) when the browser swaps from a fallback font to the custom font after it loads
  • Wasted bandwidth for mobile users on limited data plans

The fix is not switching to a system font or giving up on typography. The fix is being deliberate about which weights you load and how you load them.

Step 1: audit which weights you actually use

Open your site in the browser. Inspect the CSS. Search for every font-weight declaration. Write down which values appear: 400 (regular), 500 (medium), 600 (semibold), 700 (bold), and so on.

Then compare that list to which font weights your site actually loads. In Webflow, this is visible in the font settings. In WordPress, check your theme's font loading or the Google Fonts embed link in the page source.

The gap between "loaded" and "used" is your waste. Most sites load 5-6 weights and use 2-3.

Step 2: remove unused weights

In Webflow, go to your project fonts and deselect the weights you are not using. If you are using Google Fonts, update the embed URL to only request the weights you need.

In WordPress, this depends on your theme and font plugin. Some themes load fonts from Google Fonts via a URL like:

fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800

Each weight in that URL is a file request. Trim it to only what you use:

fonts.googleapis.com/css2?family=Inter:wght@400;700

That single change can cut font download time by 60-70%.

Want a website that turns visitors into customers, not just compliments?

Book a 15-min intro

Step 3: set font-display to swap

The font-display property controls what happens while custom fonts are loading. The default behavior on some browsers is to show invisible text until the font finishes downloading. This is called the "Flash of Invisible Text" (FOIT). Visitors see a blank page where text should be.

Setting font-display: swap tells the browser to immediately render text in a fallback system font, then swap to the custom font once it finishes loading. The text is always visible. The only trade-off is a brief visual shift when the swap happens.

If you are using Google Fonts, add &display=swap to the URL. If you are self-hosting, add font-display: swap to each @font-face declaration in your CSS.

This eliminates invisible text completely and improves both perceived speed and LCP scores.

Step 4: preload critical fonts

For the most important font weight (usually the body text regular weight), you can tell the browser to start downloading it immediately using a preload link in the HTML head:

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

This gives the browser a head start on downloading the font before it even encounters the CSS that references it. The result is earlier text rendering and reduced layout shift.

Only preload 1-2 critical font files. Preloading everything defeats the purpose and competes with other critical resources like your hero image.

Step 5: consider self-hosting

Loading fonts from Google Fonts requires a DNS lookup to fonts.googleapis.com, then a request for the CSS file, then requests for each font file. That is multiple network round-trips before a single character renders.

Self-hosting your fonts (downloading the WOFF2 files and serving them from your own domain) eliminates the DNS lookup and reduces the request chain. The browser fetches fonts from the same server as your HTML and CSS, which is faster.

Self-hosting also gives you full control over caching headers, loading behavior, and which weights are served. Google Fonts may serve different files based on the user's browser, which is helpful but unpredictable.

For Webflow, you can upload custom fonts directly. This effectively self-hosts them on Webflow's CDN. For WordPress and custom sites, download the WOFF2 files and reference them in your CSS with @font-face declarations.

CLS from font swapping

Even with font-display: swap, you may see some layout shift when the custom font replaces the fallback font. This happens because the custom font and the fallback font have different metrics: different character widths, line heights, and letter spacing. When the swap happens, text reflows and elements shift.

To minimize this:

  • Choose a fallback font that closely matches your custom font's metrics. For example, if you use Inter, set the fallback to a system sans-serif that has similar proportions.
  • Use CSS size-adjust and ascent-override properties to fine-tune the fallback font's metrics to match the custom font. This reduces the shift when the swap occurs.
  • Apply fixed heights or min-heights to text containers where layout stability matters (like hero sections and navigation).

CLS from fonts is usually small (0.01-0.05), but on sites where the hero text is the largest element, even a small shift can affect the CLS score. It is worth testing.

The font loading checklist

Here is the sequence I follow on every project:

  1. Audit which font weights the CSS actually uses.
  2. Remove every weight that is loaded but not used.
  3. Set font-display: swap on all @font-face declarations.
  4. Preload the primary body font weight.
  5. Consider self-hosting for faster delivery and more control.
  6. Test CLS in Chrome DevTools to ensure the font swap does not cause visible layout shift.

This process typically saves 100-300 KB per page and eliminates invisible text during loading. It is one of the lower-effort, higher-impact speed optimizations available, and it is almost always overlooked because nobody thinks of fonts as a speed problem until they measure it.

If your site's font loading is contributing to slow scores and layout shift, that is part of the speed and performance audit I run before any visual changes. Fonts are a quick win that compounds across every page.

Prefer to hire through Upwork?
Top Rated Plus, 100% Job Success, 450+ projects shipped. See the reviews and start a contract.
Hire me on Upwork

FAQ

How many font weights do I actually need?

Most websites need only 2-3 weights: regular for body text, bold for headings, and sometimes a medium or semibold for UI elements. Audit your CSS to see which weights are actually applied.

Should I use Google Fonts or self-host?

Self-hosting gives you more control over loading behavior, allows preloading, and avoids an extra DNS lookup to Google's servers. For performance-focused sites, self-hosting is the better choice.

What does font-display: swap do?

It tells the browser to show text immediately in a fallback font while the custom font downloads. Once the custom font loads, it swaps in. This prevents the invisible text problem where nothing appears until fonts finish loading.

All posts
the next step is small

Want a site that does this for you?

15 minutes, no deck, no pressure. Worst case, you leave with a free plan.

keep reading

More notes