The story of FOUT is so fascinating. Browsers used to do it: show a “fallback” font while a custom font loads, then flop out the text once it has. The industry kinda hated it, because it felt jerky and could cause re-layout. So browsers changed and started hiding text until the custom font loaded. The industry hated that even more. Nothing worse than a page with no text at all!
Font loading got wicked complicated. Check out this video of Zach Leatherman and I talking it out.
Now browsers are saying, why don’t we give control back to you in the form of API’s and CSS. You can take control of the behavior with the font-display property (spec).
It seems like font-display: swap;
gets most of the attention. It’s for good reason. That’s the value that brings back FOUT in the strongest way. The browser will not wait at all for an unloaded font. It will show text immediately in the best-matching-and-available font in the stack, then if/when a higher-matching font loads, it will “swap” to that.
@font-face {
font-family: Merriweather;
src: url(/path/to/fonts/Merriweather.woff) format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: Merriweather, /* Use this if it's immediately available, or swap to it if it gets downloaded within a few seconds */
Georgia, /* Use this if Merriweather isn't downloaded yet. */
serif; /* Bottom of the stack. System doesn't have Georgia. */
}
The people wanted their FOUT back, they got it. Well, as soon as font-display
is supported in their browser, anyway. Right now we’re looking at Chrome 60+ as the only browser shipping it (which means it won’t be long for the rest of the Blink clan). It’s behind a flag in Firefox already, so that’s a good sign.
But what if you don’t particularly like FOUT?
One option there is font-display: fallback;
. It’s slightly weirdly named, as it’s a lot like the default behavior (auto
or block
). The difference is that it has a really short waiting period (“font block period”), ~100ms, where nothing is shown if the font isn’t ready to go in that super short period, a fallback will be shown instead. Then the font has ~3s to get loaded and it will swap in, otherwise, it never will.
That seems pretty reasonable. What you’re preventing there is a late-term swap, which is when it’s the most awkward. Still that risk of FOUT though.
If you’d prefer that if the web font isn’t immediately available, to just show the fallback font and not ever swap to it, even after it’s downloaded. You can! That’s what font-display: optional;
does. It still gives the ~100ms font block period (giving the font a fighting chance to show up on first page view), but after that, the fallback is shown and will not swap. Chances are, the font did ultimately get downloaded, and next page view it will be cached and used.
font-display: optional;
in Chrome 60. With a clean cache, the page loads with the fallback font. The font is downloaded, but not used. Then with the cache primed, the second page load uses the font.I’m fairly open minded here. I can see how font-display: swap;
is ideal for the best accessibility of content. I’m no big fan of FOUT, so I can see the appeal of font-display: optional;
. I can also see how font-display: fallback;
kinda splits the middle.
Aside from the browser support being vital in making use of this, there is also the matter of web font providers supporting it. For example, when using Google Fonts default font loading methods, you don’t have an opportunity to use font-display
because the @font-face
blocks come from the Google-hosted stylesheets. There is an open discussion on that. There are ways to use Google Fonts with your own @font-face
blocks though. Definitely consult Zach Leatherman’s guide.
I’m so excited for this!
I prefer swap but for me its only been an issue when content added via ajax requires a font not already loaded, and that is better solved by font preloading. Also not yet available in all browsers, but seems to work in Chrome now.
I would prefer FOUT if it where easy to change CSS before/after loading the font.
That would make it possible to mimic the target font spread/width with specific
letter-spacing
,line-height
,font-weight
during the page load. When the final font is downloaded and swapped all those ‘loading-styles’ should be removed and the user wouldn’t be bothered much because the swap is gentle.This site makes it easier to find the configuration which best mimics a target font:
https://shtrihstr.github.io/font-fallback/
It really depends on what the fallback fonts are. If they are not so much of a difference, then I would opt for the
font-display: optional
.Of course, we’ll still need to do testing for which
font-display
works best for a given situation.So if we’d like to get the font loading ASAP, we’ll go for
font-display: swap
.