Web fonts and speed: how to load them faster
How web fonts slow a page down and how to fix it: fewer files, WOFF2, subsetting, the right font-display value, early loading and matched fallbacks.
In this guide
How fonts slow a page down
A web font is a file the browser has to download before it can draw text in that typeface. That creates three separate problems, and each has its own fix.
- Weight. A page with a display font in four weights, plus an icon font, may load half a dozen files. In the 2025 Web Almanac, the median mobile home page loaded 122 kilobytes of fonts, and the largest sites loaded much more.
- Invisible text. Until the font arrives, the browser can hold the text back. That delays First Contentful Paint, and when the main element of the page is text, it delays LCP too. The browser does not count text as drawn while it is invisible during the font's block period.
- Layout shift. When the font swaps in, text can change size, and the page below moves. See layout shift.
Step 1: find out what you load
Open the Network panel in Chrome DevTools, filter by Font, and reload. Write down every file: the family, the weight, the format and the host. A typical surprise is a theme that loads three families, each in five weights, and a page that uses two of them. Each file you do not need is a download that blocks nothing, but competes with files that do.
Step 2: load fewer, smaller files
Remove what the page does not use. Fewer families, fewer weights, no italics unless you use them. Check the theme's typography settings first, because many load every weight by default.
Serve WOFF2. It is a compressed format, supported by all modern browsers, and it covers everything fonts need, including variable fonts. You rarely need to ship a second format now.
Consider a variable font if you use several weights of one family. A variable font puts a whole range of weights in one file. That file is larger than a single static font, but in most cases smaller than, or about the same size as, the four or so files for the weights of a body text family. If you use only one or two weights, static files are usually smaller.
Subset and split. A font file contains thousands of characters, and most pages use a small part of them. Subsetting removes the characters you will not need, such as other alphabets. Splitting is the other approach: define the same family several times, one for each range of characters, with unicode-range. The browser then downloads a file only if the page uses a character in its range, so a Latin-only page never downloads the Cyrillic file:
@font-face {
font-family: "Brand";
src: url("/fonts/brand-latin.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153;
font-display: swap;
}
@font-face {
font-family: "Brand";
src: url("/fonts/brand-cyrillic.woff2") format("woff2");
unicode-range: U+0400-04FF;
font-display: swap;
}Step 3: load the important ones early
By default the browser finds a font only after it has downloaded the CSS, read the rules and found text that uses the font. That is late. A preload hint lets it start the download while it reads the HTML:
<link rel="preload" href="/fonts/brand-latin.woff2" as="font" type="font/woff2" crossorigin>The crossorigin attribute is required even for fonts from your own domain, because the browser always fetches fonts in a mode that uses CORS, and a preload without it does not match the real request: the file would be downloaded twice.
Preload sparingly: one or two fonts that the first screen needs, usually the body text and the main heading font. A preloaded font that the page does not use wastes bandwidth that images and scripts could have used.
Step 4: choose font-display
The font-display descriptor says what the browser should do while the font loads. Two periods matter: the block period, when text in that font is drawn invisibly, and the swap period, when a fallback font is drawn and the real font replaces it when it arrives.
| Value | Block period | Swap period | Use it for |
|---|---|---|---|
block | Short | Unlimited | Icon fonts, where a fallback letter would be nonsense |
swap | Extremely small | Unlimited | Body text and headings: show text at once, then swap |
fallback | Extremely small | Short | A compromise: swap only if the font arrives quickly |
optional | Extremely small | None | Decorative fonts: use the font only if it is already there |
auto | The browser decides | Avoid: the result differs by browser |
For most sites, swap is right, paired with a fallback tuned to the same proportions so the swap does not move anything. Where layout stability matters more than showing your exact typeface on the first visit, optional gives the least shifting: on a slow connection the visitor sees the fallback for the whole visit, and on later visits the font is cached and used. The Lighthouse insight called Font display lists fonts with a setting that hides text, and its text recommends swap or optional.
Step 5: match the fallback
A swap changes the size of the text unless the fallback matches. CSS lets you scale a local font and set its line metrics so that it takes the same space as your web font. That keeps the swap almost invisible, and it is covered with the code in how to fix layout shift, and step by step in fixing layout shift from web fonts. Frameworks such as Next.js generate these fallbacks automatically.
Where the font comes from
Self-hosting. Serving the files from your own domain removes a connection to a third-party host, lets you control caching and preloading, and avoids a render-blocking stylesheet request to the host. Third-party hosts. They were once attractive because a popular font might already be cached from another site. Browsers now partition their caches by the site you are on, so a file downloaded for one website is not reused on another; MDN documents this for Firefox since version 103 and the same idea applies to other browsers. If you do use a font host, add a preconnect for its file domain, with crossorigin, and ask for a swap display value if the service offers one.
System fonts. A font stack such as system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif uses the fonts already on the visitor's device: nothing to download, no invisible text and no swap. It is a fair choice for body text, and many fast sites use it. Whether your brand needs its own typeface is a design decision with a price you can now measure.
Icon fonts. One font file for dozens of icons, most of which you do not use. Inline SVG icons, one per icon actually used, are lighter and cannot fail to load.
A checklist
- Remove families and weights the page does not use.
- WOFF2 only, subset to the characters you need, split with
unicode-rangeif you serve several alphabets. - Preload one or two fonts, with
crossorigin. font-display: swaporoptional;blockonly for icons.- A fallback font matched to the web font.
- Self-host, or preconnect to the host.
- Test on a slow connection and watch the first second.
On WordPress and page builders
Themes and builders often load fonts in ways you cannot see in the content. Look at the typography section of the theme settings, and at the font settings of the builder, for options such as "load only the weights used" or "host fonts locally". A plugin that moves Google Fonts to your own server and sets the display value is a common fix, but check the result in the Network panel: it should end with fewer files, not just different ones.
To see how common these habits are, read web fonts in 2025, which sets out what real sites do.
Check your own page
Run the free audit and look at the Font display insight and the number of font files in the request list. If text appears late, or the page jumps when it finishes loading, fonts are the first suspect. Fix the number of files, then the display value, then the fallback.
Sources
- font-display on MDN: the block and swap periods and each value.
- unicode-range on MDN: downloading a font only when it is used.
- rel="preload" on MDN: preloading fonts and the
crossoriginrequirement. - Variable fonts guide on MDN: one file for many weights.
- Font fallbacks in the Chrome documentation: matching a fallback to a web font.
Start here
Free website audit
Live Google data for any public page: mobile and desktop.
Mobile + desktop · Lighthouse lab test · Real-user Chrome data when Google has it
Rather have this done for you? Speed optimization · Book a call