This is a small explainer that I built for a talk on web fonts and performance.

Before we talk about what font-display is, let's talk about the lifetime of a web font. For a super detailed explanation of where web fonts fit in the browser rendering process, Ilya Grigorik has an amazing blog post on web font optimization. But, if we're just trying to understand the basics, there are basically three parts to it:

During the block period, the browser renders your text in an invisible font. This is why on a lot of webfont-heavy websites, during the first load of the page you will see no text or worse, phantom underlines.

One of the downsides of using web fonts is that if a font is not available on a user’s device, it must be downloaded. This means that before the font becomes available the browser has to decide how to handle the display of any block of text that uses that font. And it needs to do so in a way that doesn’t significantly impact the user experience and perceived performance.

In the course of time, browsers have adopted several strategies to mitigate this problem. But they do this in different ways and out of the control of developers, who have had to devise several techniques and workarounds to overcome these issues.

Would you suggest icon fonts or inline SVGs for a complex single page application? And are there specific accessibility concerns for either? Accessibility is especially important for us because schools use our products. I ask because we are currently in the process of unifying and setting up an icon system.

I don't think I would make the choice based on what "kind" of website I was building, so let's ignore that part of it.

I also think SVG icon systems are just better than icon fonts, so let's assume that.

The accessibility question is the interesting bit, so let's cover that.

Before custom fonts are displayed, they need to be loaded first. There are three possible scenarios for font loading:

Scenario 1 only happens when you try to use a nonexisting font, or a declaration with a bad src. This can and should be avoided entirely. Jumping to Scenario 3, it is the best case scenario and can usually be achieved through proper font caching. Scenario 2 is the scenario that involves font loading. Font loading is mostly unavoidable (at least for the first request instance). There are several ways to deal with it:

1. Flash of Unstyled Text (FOUT). A FOUT is an instance where a web page uses default and fallback fonts before switching to the proper web font. It happens because font requests do not happen until both HTML and CSS are downloaded. This means that there is a period of time where HTML is displayed before fonts are fully downloaded.

When people talk about progressive enhancement it is often reduced to JavaScript. It involves much more – accessibility, performance, robustness… and also CSS. Badly written CSS can make a site as usable as a JavaScript error or using non-semantic HTML.

Let’s see why CSS can fail, why fallbacks are important and how to progressively enhance CSS.

Fallbacks

CSS has changed a lot in the last years. More and more properties were added and while some are now supported in all modern browsers some only work in one or two browsers. In any way, we can often make use of the architecture of CSS. If a browser doesn’t know a property it will simple skip it without throwing an error. Let’s have a look at an example to demonstrate this:

When people talk about progressive enhancement it is often reduced to JavaScript. It involves much more – accessibility, performance, robustness… and also CSS. Badly written CSS can make a site as usable as a JavaScript error or using non-semantic HTML.

Let’s see why CSS can fail, why fallbacks are important and how to progressively enhance CSS.

Fallbacks

CSS has changed a lot in the last years. More and more properties were added and while some are now supported in all modern browsers some only work in one or two browsers. In any way, we can often make use of the architecture of CSS. If a browser doesn’t know a property it will simple skip it without throwing an error. Let’s have a look at an example to demonstrate this: