Web font patterns displaying and CSS's font-display property

I really don't like use custom web fonts. Importing custom web fonts on the first visit negatively affects the performance of the web page. But as web developers and designers, we always try to create a beautiful, smoothly working site and lets try to import fonts and keep a balance beetween aesthetics and performance. New CSS's font-display property helps us with it.

For begining, we shall understand how are connecting the fonts and the browser render them. We will look at patterns such as FOIT, FOUT, FOFT and will know how to use new CSS's property. All links on the bottom page.

How to load custom fonts correctly?

The best font is that we didn't connect. Many good built-in fonts. Besides, there is a tendency to use system fonts for different devices.

  • This generic font family is intended to let text render with the default user interface font on the platform on which the user agent is running. Now it works like that

font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira, Sans, Droid Sans, Helvetica Neue, sans-serif;

Or just use system-ui in the future.

<div id="system-text" style="font-family: system-ui"></div>

  • If we need load custom font, we use @font-face. When the browser sees the font-face directive, it doesn't immediately rush to load everything, but it differs from the background images. It parses all the rest of the css and waits for the moment when the text will need to render this font and only then sends a request for the files. Note, Woff2 has the best compression, others formats is needed for supporting old browser.
@font-face { 
    font-family: Output Sans;
    src: url(output-sans.woff2) format('woff2'), 
         url(output-sans.woff) format('woff'); 
}
  • By the way, everyone likes Google fonts for easiest import, but it's not good one because function import block loading page. @import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i');

  • We can add local names. Browser will try to find it locally and only after that will load fonts from file.

src:
	local('Roboto Light'),
	local('Roboto-Light')
src:
	local('PT Sans'),
    local('PTSans-Regular')

Web font patterns

1. Flash Of Invisible Text

If the browser immediately see that it needs a font, it starts loading it. At this moment most browsers hide the text and wait while the font loads => The effect of Flash Of Invisible Text.

Chrome, Firefox, Edge stop waiting after 3 seconds and load the next font in the list. That's why it's important to have a spare list. Chrome on slow networks does not wait at all, and safari 9 and the old android wait until the last.

2. Flash Of Unstyled Text

IE shows immediately the next system font while waiting for the download. When the font is loaded, the text is rerender. it is called "Flash Of Unstyled Text" and this effect is considered the most successful. For example, library Font Observable tries to simulate this, and has different settings.

3. Flash Of Faux Text

The idea here is only waiting for the Roman variant of the custom font to load, and setting text in that right away. You force the browser to create "faux bold" and "faux italic" where needed, which are replaced by the real versions as soon as those are downloaded. In this case, text will rerender 2 times. A good tool to prevent jumping text flickering is Font style matcher.

We can see different patterns for displaying web fonts, but it depends on browser, we coudn't manage it. Font-display allows you to control the way that the font is displayed at boot time.

Font-display

Using font-display, you can tell the browser how to load the font. For example, specify how important your font is and when the system refuses to load the font in case it takes too long. You can add a font-display property to your @ font-face rule.

@font-face {
  font-family: 'Roboto';
  font-display: auto;
  src: local('Roboto'), url(https://github.com/abadkingdog/viblo/blob/master/fontDisplay/fonts/Roboto-Regular.woff2) format('woff2');
}

Values

Block - an invisible text on 3 sec If you still decided that your font is very important, use font-display: block. This property tells the browser to wait a while (about three seconds) to load the fonts. At this time, the user will not see any text. After three seconds, the next font will be used. From now on, no matter how long the browser downloads fonts, it will replace the recently downloaded one to the backup, even if the user has already started scrolling and reading your page.

Swap - show system font immediately If your custom font is critically important for website design, there is a better option for you. Font-display: swap immediately uses a backup font. In this case, as soon as you finish loading your custom font, be it in a second or 5, the browser will replace the backup font with your custom font. It is worth noting that changing the font can annoy the user, especially if he has already focused on reading.

Fallback - almost immediately shows the system and will not wait long for the download. The browser itself decides whether to load the font. If you set the font-display property to fallback, the browser will wait for less than a second while your custom font loads. If the font does not load at this point, the rollback will be used. In this case, the user does not have to long look at the blank page. The catch, of course, is that your beautiful custom font will not be loaded on this page, and it may spoil the look and feel of your site. Font-display: fallback is very straightforward: if your font does not load on time, it will not be used.

Compatibility

Compatibility is still not well, Chrome have been supporting this property since only version 60.

PC

Feature Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
Basic support 60 ? 46.0 (46.0)[2] No support 36[1] ?

Mobile

Feature Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support No support ? 46.0 (46.0)[2] ? 37[1] ? 59.0[1]

How to choose a value?

If performance comes first, and custom fonts do not really bother you, then font-display: fallback is your choice. If the custom font is very important, then swap and block for you. Keep in mind that whatever method you use, first test everything well. Demo here

Conclusions

It's only short description how web fonts works now and how it will works in the future. I recomment seeing W3C First Public Working Draft [4] there are many new properties wait for us in the future like font-stretch, font-size-adjust, the font-min-size and font-max-size and others. I hope one day it will do our web sites more responsive and flexible.

Links

  1. A COMPREHENSIVE GUIDE TO FONT LOADING STRATEGIES
  2. Font style matcher
  3. Controlling Font Performance with font-display
  4. Controlling Font Display Per Font-Face: the font-display descriptor
  5. Demo Font display