Fix Ensure text remains visible during webfont load
Webfonts must be downloaded before use, causing text to hide temporarily during loading.

"Ensure text remains visible during webfont load" in short
Webfonts are fonts that aren't available by default for use on a web browser. What you get is that webfonts have to be downloaded before they can be used. While downloading a webfont, the text on a webpage is temporarily hidden until the webfont has been loaded.
As a result, it will seem like the page loads a lot slower because the page hasn't "finished" loading for visitors to use. This could lead to a reduced user experience. When you run a Lighthouse analysis on your page, a warning about the page load performance appears: "Ensure text remains visible during webfont load".
Solve this by changing the font-display value or by using a font loader. I explain how this works in this article.
Last reviewed by Arjen Karel on February 2026

Make sure that the text remains visible while loading webfonts
Before webfonts existed, web designers were stuck with just a small number of pre-installed fonts. Webfonts give you the freedom to use any font on a website.
Of course that sounds nice, but webfonts also have their disadvantages; they slow down the loading page speed in several ways.
Webfonts are usually large files which are not installed on a computer by default. So webfonts must be downloaded before they can be used. While downloading a webfont, the text on a webpage will be temporarily hidden until the webfont has been loaded completely. This makes for a poor user experience; nobody wants to stare at an empty screen for too long.
As soon as the webfont is loaded and rendered, the browser replaces the "invisible text" for the final text with the new webfont. This moment is called the Flash of Invisible Text (FOIT). This FOIT is what causes the "Ensure text remains visible during webfont load" error message to appear.

Loading a webfont on your page and not taking any precautions to prevent this Flash of Invisible Text? While you analyze the PageSpeed on Lighthouse, the following message will appear: "Ensure text remains visible during webfont load". This tells you how much time you could save by making the text visible before the webfont is loaded. For 1 single font, this is easily 100ms.
Why is invisible text bad for page speed?
Invisible text won't really slow down the final measured loading time of a page. So why does Lighthouse think it's such a problem?
Google thinks it's important a web page provides the best user experience possible. The user experience can be improved by showing content on the page as fast as possible. Invisible text directly affects your First Contentful Paint (FCP) because the browser cannot paint text it is hiding. If text is your Largest Contentful Paint (LCP) element, FOIT delays that metric too. Compare the two filmstrip versions of our homepage below:
Flash of Invisible Text
No flash of invisible text with display:swap
As you can see, the two pages finished loading at exactly the same time. Still, the latest version of the website looks a lot better to visitors. Visitors can start reading immediately.
That's why it's smart to show text anyway, not in the final font, but in a "fallback" font. This way the visitor thinks your page really does load superfast.
A brief reminder: FOIT and FOUT
Before we go any further, it's helpful to distinguish the following concepts: FOIT and FOUT. FOIT stands for the Flash of Invisible Text and occurs when webfonts are not visible during loading. You can mitigate this by including a fallback font. When the fallback font is replaced by the webfont, it is called FOUT, Flash of Unstyled Text.
Make webfonts visible during loading
There are two ways to make webfonts visible during loading: first is via the CSS font-display value; second is by using a fallback font via a class. Both methods have advantages and disadvantages, which I will discuss below.
Method 1: Font-display:swap
Font-display is a CSS descriptor that is available to all modern browsers. The font-display descriptor determines how a font is displayed based on if and when it was downloaded. Font-display is used in a @font-face rule.
There are four font-display values you should know about:
- swap: Shows the fallback font immediately, then swaps to the webfont when it loads. The swap window is infinite, so the webfont always replaces the fallback eventually. Best for brand fonts and headings.
- optional: Shows the fallback font immediately. The browser decides whether to swap based on connection speed. No swap means zero layout shift. Best for body text where performance is the priority.
- fallback: Shows the fallback font immediately, then gives the webfont a short window (~3 seconds) to load. If it misses the window, the fallback stays. A middle ground between swap and optional.
- block: Hides text for up to 3 seconds while the font loads. This is the cause of FOIT. Do not use this unless you have a specific reason (like icon fonts).
According to the 2025 Web Almanac, only 50% of sites use font-display: swap, while 25% still use block. That means a quarter of the web is still showing invisible text during font loading.
Use the swap value to avoid FOIT and have the text appear on the screen as fast as possible. Once we set the font-display: swap value in the @font-face rule, the system's default fonts are used while the page loads until the webfonts have been loaded. This helps the visitor read the text on the page immediately.
Google Fonts
When using Google Fonts, you can use the font-display: swap method with a simple "&display=swap" in the stylesheet or embed code.
<!-- via an external stylesheet -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet"> <!-- via the import method (slower, not recommended) -->
<style>
@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
</style> The @import method is render-blocking and forces the browser to download stylesheets sequentially. The <link> method is faster because the browser can discover the font stylesheet earlier in the parsing process.
But we're not fans of either approach. It's almost always much faster to host webfonts yourself. It gives you more control over the "preloading" process of the fonts. You can use the already existing HTTP/2 connection and you don't have to download an extra stylesheet.
Local fonts
@font-face {
font-family: "Open Sans";
font-weight: 400;
font-style: normal;
src: url("OpenSans400.woff2") format("woff2");
} WOFF2 is all you need. It is supported in every modern browser and offers the best compression. According to the 2025 Web Almanac, 72% of sites now self-host their fonts, and WOFF2 accounts for 65% of all web font requests. There is no reason to include WOFF or TTF as fallback formats anymore.
Prevent layout shift when swapping fonts
There is a catch with font-display: swap. When the browser swaps from the fallback font to the webfont, the text often changes size. Different fonts have different character widths, ascent heights, and line spacing. This size change causes Cumulative Layout Shift (CLS), which is a Core Web Vital.
The fix is the size-adjust CSS descriptor. It scales the fallback font to match the dimensions of your webfont, so the swap causes little to no visible shift. Browser support is above 93%, including Safari 17+.
/* Define a matched fallback font */
@font-face {
font-family: "Open Sans Fallback";
src: local("Arial");
size-adjust: 105%;
ascent-override: 110%;
descent-override: 25%;
line-gap-override: 0%;
}
/* Use both in your font stack */
body {
font-family: "Open Sans", "Open Sans Fallback", sans-serif;
} The ascent-override, descent-override, and line-gap-override descriptors give even more precise control over the vertical metrics. These work in Chrome, Firefox, and Edge but not yet in Safari, so treat them as progressive enhancement. The size-adjust property alone already makes a noticeable difference.
Across sites monitored by CoreDash, pages that combine font-display: swap with font metric overrides have [CD:placeholder]% less font-related CLS than pages using swap alone.
Method 2: Fonts with a class
The second way to make fonts visible during loading is to work with classes. These classes are usually (but not always) added to the <body> or <html> element.
The advantage of this method is that you have more control over the fallback font and the timing of the Flash of Unstyled Text.
This method works as follows: Indicate in your stylesheet that a page should initially be rendered with a font (the fallback font). You then load the webfont via the JavaScript FontFace API or via preloading. After this font has been loaded, add a class to your page. The class makes sure the webfont is activated.
Why would you do that, you might ask? You do this to gain more control over the fallback font. You can display the fallback font with a larger line spacing or a different size so it matches the webfont better. This prevents layout shifts.
When using multiple webfonts, you can use the FontFace API method to switch all fonts at once. This saves a lot of browser repaints. Personally I am not a fan of this method; this ensures that FOUT takes place after the last font has been loaded. So that is always later than necessary.
Font with a class via the FontFace API:
<style>
// fallback font with a .9rem font-size
html{
font-family: sans-serif;
font-size:.9rem;
}
// webfont with a 1rem font-size
html.fl{
font-family: 'webfont';
font-size:1rem;
}
</style>
<script>
var font = new FontFace("webfont", "url(/font.woff2)", {
style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});
// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
document.fonts.add(font);
document.documentElement.classList.add("fl")
});
</script> Via a preload link
The second method is via a preload link. Preload the font as described below. Once this is done, switch the class of the <html> element.
<link
rel="preload"
href="/webfont.woff2"
as="font"
type="font/woff2" crossorigin
onload="document.documentElement.classList.add('fl')">
<style>
// fallback font with a .9rem font-size
html{
font-family: sans-serif;
font-size:.9rem;
}
// webfont with a 1rem font-size
html.fl{
font-family: 'webfont';
font-size:1rem;
}
// @font-face, only activated once the .fl class is added to the html tag
@font-face{
font-family:'Open Sans';
font-style:normal;
font-weight:400;
font-display:swap;
src: url(/webfont.woff2) format("woff2");
unicode-range:U+000-00FF;
}
</style> Extra tips and tricks
- Always preload visible fonts. Fonts are not downloaded by default until they are actually used on a page. If you need a webfont, preload it so it is available sooner.
- Want to avoid FOIT and FOUT entirely? Use font-display: optional in combination with preloading.
- Hosting webfonts yourself is always faster than webfonts via Google Fonts or another external CDN.
Want to verify that your font loading strategy actually improves real user experience? Use Real User Monitoring to track your FCP and CLS before and after making changes.
Pinpoint the route, device, and connection that fails.
CoreDash segments every metric by route, device class, browser, and connection type. Real time data. Not the 28 day average Google gives you.
Explore Segmentation
