How to use asynchronous font loading
Recently we announced a release of our asynchronous font loading, which is available through all of our kits on Fort Awesome. With it came some backward-incompatible changes that we felt were needed to clean up our initial release.
One comment we’ve received from a lot of users is: “How do I use this?” So we thought we’d take time to go over some patterns for async font loading and how you can use this feature.
What is synchronous (or blocking) loading?
With normal synchronous loading, the browser will see this addition to the Document Object Model (DOM) and block rendering of the page until the CSS finishes loading. For your main site’s CSS, this is exactly what you want. If the browser didn’t wait on this CSS, you would get a flash of unstyled content before seeing the real page.
While you care about your main CSS, your icon font and typefaces are probably not critical enough to block page rendering. We want our pages to load and display content to the user as quickly as possible. Loading a site just 1 second faster can yield drastic improvements in conversion rates.
What is asynchronous (or non-blocking) loading?
This causes content on the page to display before the icons or typefaces from your kit finish loading. This has a positive effect on performance while having some negative effects on how the content is displayed.
With Fort Awesome and Font Awesome CDN, you can choose either normal loading or asynchronous loading.
There are some potential downsides to asynchronous loading we’ll cover in detail:
- Flash of unstyled text (FOUT) — text that displays to the visitor in the default browser font because the real typeface hasn’t loaded
- Flash of invisible text (FOIT) — text that is missing from the page until the typeface has loaded
- Invisible font variant text — bold or italic variants that show up as gaps in otherwise visible text until the typeface variant is loaded
- Layout shifting — elements utilizing icons that suddenly get wider after the icon font has loaded
Yuck, right? These don’t only occur on slower connections or under failure conditions but can happen at any time. Luckily we have some techniques to handle it.
Font events from Font Awesome CDN and Fort Awesome
To conquer some of these drawbacks requires the right tools so that you can craft a solution.
Let’s go source-diving and take a quick look at an example:
This event indicates the status of the icons for the page. While icons are loading, you’ll see “fa-events-icons-loading.” After they finish, you’ll see “fa-events-icons-ready.” Should the icons fail to load you’ll see “fa-events-icons-failed.”
This event indicates the overall loading status of an individual typeface. An example would be “fa-events-typefaces-lato-ready”.
This more specific typefaces event includes weight and style to provide more specific targeting by font variant. An example would be “fa-events-typefaces-lato-300-normal-ready”
Deciding how your page will load
There is no magic solution. Ultimately, you have to decide how you want your pages to load. Here are the most common things that we’ve run into and how you can implement them using Fort Awesome and Font Awesome CDN. If you have other ideas, we’d love to hear about them.
For this example, I’m using Fort Awesome with an icon from Black Tie, two custom icons, and four typefaces. Fort Awesome makes it easy to pull all those pieces together.
Without any modification, this is how our page loads:
Using a fallback font
Problem: the transition between the browser’s default font and the site’s typeface is very jarring
Solution: use a fallback font that is closer to the site’s actual typeface
Since this page uses Lato in its actual design, we can fall back to a sans-serif typeface to minimize the visual difference between it and the browser’s default Times Roman.
Using “fa-events-typefaces-lato-loading” combined with our elements that use Lato we can target just those elements and change the font-family to “sans-serif.”
Hiding elements that require icons or typefaces
Problem: some elements require icons or typefaces to make visual sense to the user and shouldn’t be displayed until they are ready
Solution: surgically hide elements or sections that require icons or typefaces until they are loaded
With this example, we completely hide the Mr. Fusion logo until the typeface and icon are loaded. The main content is available right away, and since we are using “visibility: hidden;” space is still present on the page for the brand to fill.
Keeping icons from messing with your layout
Problem: the layout of buttons and other elements shift drastically after the icons load causing the page to reflow
Solution: use fixed layout icons and create a placeholder for them
This approach utilizes “fa-fw” to make icons a fixed width. We then use some additional CSS to create placeholders in the content.
Here the loading state is used to target all “fa-fw” elements and force them to be inline-block. The width 1.28571429em; comes from the “fa-fw” definition. By matching these two values, our icons will not experience any shifting while they are loading.
The section definition “fa-fw::before” targets the icon’s content. For the browser to display the placeholder, it has to have some text in it. “\00a0” is a non-breaking space and works great for this purpose.
The last step in this scenario is to add “fa-fw” to the icons that should be placeholders on the page.
Blocking display of everything until icons and typefaces load
Problem: when the page loads, there is a brief moment when the text is in the wrong font (FOUT) or is not visible (FOIT)
Solution: hide the entire <body> until the icon and typefaces load
This is the nuclear option, and we do not recommend it. It’s much better to use specific techniques to accomplish nuanced effects. But, sometimes, you need the nuclear option.
By using the “fa-events-icons-loading”, “fa-events-typefaces-lato-loading”, and “fa-events-typefaces-orbitron-loading” we can hide the entire <body> of our page until they are ready.
This solution works well if the icons and fonts should fail to load because the “loading” states will get replaced with “failed.” With the loading state missing, the body will display as normal.
While this technique avoids FOUT, FOIT, and any layout issues, it’s the slowest approach. It’s also very similar to normal blocking loading. So if this approach sounds like the behavior you want, you might also consider turning async loading off.
Bringing it all together
Combining three of the mentioned techniques, we finish off with an example that still displays the main content while minimizing layout and visual shift. With a little more work, we could get things even closer.
Hopefully, this provides some useful examples of how you can leverage asynchronous loading to get better performance while managing the trade-offs that come with it.
If you have any suggestions, comments, or issues, please let us know about it!