Menu

How to avoid "flash of invisible text" (FOIT)

How to avoid "flash of invisible text" (FOIT)

Fonts have become so increasingly complex during the past decade to the point where you probably need to set up a development meeting with your team in order to discuss just adding a new one to a page. And that's mainly because there are just many more options now when it comes to using a specific font.

Where in the past you mainly had to rely on built-in system fonts, such as 'Arial' or 'Helvetica', you now have the ability to seamlessly integrate thousands of fonts with a simple declaration.

<style>
@import url('https://fonts.googleapis.com/css2?family=Lato:ital,wght@1,300&display=swap');
</style>

But that doesn't come without a price.

The first issue is the dreaded "flash of invisible text", or FOIT. Essentially, most browsers will not load text content until the particular font that the content uses has been loaded to the page. This wasn't always the case in the past.

in the mid-2000's browsers would initially load the content using a default system font. When a new font was fully loaded onto the page, the text would switch font families. Depending on the length of time needed to load a particular font, you might end up with a flicker that might cause a cumulative layout shift.

Back then that wasn't a big issue, though unsightly to look at, however now, that is not recommended given the core web vitals guidelines.

There are several to fix this issue however. Let's start with the simplest solution:

font-display

The quickest solution to prevent FOIT is to replace it with FOUT (flash of unstyled text). Which is not at all the most ideal solution, particularly if you want to maintain a consistent design. But it is a viable solution.

You can do that by loading a default system font as a fallback, until the proper font has finished downloading to the clients browser.

The font-display CSS property allows you to specify how the browser treats the loading of fonts. More specifically, the swap value of font-display will quickly load a default font and then wait to render any subsequent fonts once they have finished loading.

@font-face {
  font-family: 'Pacifico';
  font-style: normal;
  font-weight: 400;
  src: local('Pacifico Regular'), local('Pacifico-Regular'), url(https://fonts.gstatic.com/s/pacifico/v12/FwZY7-Qmy14u9lezJ-6H6MmBp0u-.woff2) format('woff2');
  font-display: swap;
}

The other potential values for font-display are as follows:

auto - The font display strategy is defined by the user agent.

block -Gives the font face a short block period and an infinite swap period.

swap -Gives the font face an extremely small block period and an infinite swap period.

fallback -Gives the font face an extremely small block period and a short swap period.

optional - Gives the font face an extremely small block period and no swap period.

Because swap gives an infinite swap period however, there is a chance that the FOUT (flash of unstyled text) will be heavy, or even worse, that the layout shift will be noticeable to the user.

In that particular case, the fallback option might make the most sense, as it still gives a very short initial wait period followed by a short swap period of 3s. If nothing is loaded within the 3s time period, the font never switches.

If you are looking to almost completely remove the chance of FOUT however, then the optional value might make the most sense to you, though it is the most restrictive as it will wait the initial 100ms wait time before no longer loading a font.

The idea here being that once the user has loaded the page, the new font will be cached on their local machine and thus provide almost instant rendering on any subsequent page loads.

Walter G. author of blog post
Walter Guevara is a Computer Scientist, software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20 years.

Get the latest programming news directly in your inbox!

Have a question on this article?

You can leave me a question on this particular article (or any other really).

Ask a question

Community Comments

No comments posted yet

Add a comment