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

Written by
Published on
Modified on

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.

@import url(',[email protected],300&display=swap');

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:


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( 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 Guevara is a software engineer, startup founder and currently teaches programming for a coding bootcamp. He is currently building things that don't yet exist.


No messages posted yet

Developer Poll 🐱‍💻


Add a comment

Send me your weekly newsletter filled with awesome ideas