SolisReach
← Journal
Web Performance5 min read

The font-loading mistake that's costing you LCP

Written by the SolisReach team

Custom fonts make a site look intentional, and almost every brand-conscious client wants at least one. The problem is how often they're implemented in a way that blocks the browser from painting any text at all until the font file finishes downloading, which can add a full second or more to Largest Contentful Paint on a slow connection, all for a typography choice most visitors won't consciously register.

This is one of the most common findings in our performance audits, and one of the least understood by the teams whose sites we're auditing. Nobody chose to make text invisible for a second and a half. It happened as a side effect of how the font got added to the project, usually copied from a starter template or a design handoff without anyone checking what the loading behavior actually did to the page.

font-display is the single highest-leverage fix

Setting `font-display: swap` (or `optional` for less critical fonts) tells the browser to render text in a fallback font immediately and swap to the custom font once it loads, instead of leaving the page blank. It's a one-line CSS change that alone has fixed a meaningful share of the LCP issues we find in audits, and it's astonishing how often it's simply missing.

The default behavior without this property, `font-display: block` in most browsers, gives the browser a window of up to three seconds to hide text entirely while waiting for the font, then falls back if it hasn't loaded by then. On a fast connection that window rarely gets used, which is exactly why it goes unnoticed in local development. On a real mobile connection with real latency, that three-second block window is often the entire difference between a passing and failing LCP score.

Preload the fonts actually used above the fold

A `<link rel="preload">` for the specific font file weights used in the hero section tells the browser to fetch it early, in parallel with other critical resources, instead of discovering it late after parsing the CSS that references it. Preloading every font weight on the site, though, just adds unnecessary early network contention for files that aren't needed yet, so this needs to be scoped narrowly.

We typically preload no more than two font files: the primary body weight and whatever heavier weight the hero headline uses. Anything used below the fold, a light italic variant for pull quotes, for instance, can load normally without competing for bandwidth during the page's most critical first second.

Self-host instead of pulling from a third-party font service

Google Fonts and similar services are convenient, but every request to a third-party domain adds a DNS lookup and a connection handshake before the font file itself even starts downloading. Self-hosting the font files on the same domain as the rest of the site removes that entire round trip, which on a slow connection can be worth more than the font-display fix on its own.

This also removes a dependency on a third party's uptime and a privacy consideration some clients care about more than others, since a third-party font request is technically a request that can be used for tracking. Neither is the primary reason to self-host, but both are a reasonable bonus on top of the performance win.

Sometimes the fix is fewer font files, not better loading

We regularly find sites loading four or five weights of the same typeface when the design only actually uses two. Every additional weight is another network request competing for bandwidth during the page's most critical loading window. Trimming unused weights is boring, unglamorous work, and it's often worth more to LCP than any amount of clever loading strategy applied to files that didn't need to be there.

This usually happens because a design system gets set up early with a full type scale, semibold through black, italic and non-italic, and only two or three of those weights ever actually get used once the site is built. Nobody goes back to remove the unused font files because removing things feels riskier than leaving them, even though the unused files are pure cost with no offsetting benefit.

We regularly find sites loading four or five weights of the same typeface when the design only actually uses two.

Variable fonts change the math, sometimes for the worse

A single variable font file can technically replace five or six static weight files, and that sounds like an obvious win. It often is, but not always: a variable font file containing every weight and width axis a typeface supports can be larger than the two or three static weights a given site actually uses, especially for typefaces with a wide range of variation axes.

The right call depends on the specific typeface and how many weights the design actually needs. For a design using just two weights, static files are usually smaller and simpler. For a design genuinely using four or more weights across the site, a variable font is usually the better trade. We check the actual file size comparison for the specific typeface rather than assuming variable fonts are always the lighter option.

How we check this in an audit

The check itself takes about two minutes: open the network tab, filter to font files, and look at both the request timing relative to page load and the `font-display` value applied in the CSS. A font file that starts loading late, competes with other render-blocking resources, or has no `font-display` set at all is an immediate flag, and it's usually one of the first three things we fix on any performance engagement, because the fix is cheap and the impact on Largest Contentful Paint is disproportionately large.

We also check whether the font referenced in the hero headline's CSS actually matches a preloaded file. It's a small mismatch, a preload tag pointing at the wrong weight or format, but it's common enough that we treat checking it as a standard step rather than an edge case, since a mismatched preload wastes bandwidth on a file the page doesn't end up using at all.

Why this fix rarely gets prioritized on its own

Font loading almost never makes it onto a roadmap as its own line item, because it's invisible to anyone not specifically profiling page load. A marketing team notices a slow-feeling site and blames images or third-party scripts, both reasonable guesses and both genuinely worth checking, but font loading rarely gets named as a suspect until someone actually opens the network tab and looks.

That's part of why it's one of the first things we check on a new audit rather than something we wait for a client to flag. The fix is cheap, the diagnosis is fast, and the win shows up directly in the Core Web Vitals numbers a client already cares about for entirely separate SEO and ad-spend reasons.

Start a project

Want this applied to your site?

We run a Core Web Vitals and SEO audit before quoting any performance marketing engagement, and we're happy to share what we'd find on yours.