Trung Nguyen
Trung Nguyen

Reputation: 529

How to lazy load web font declared by @font-face?

What I've got is a font-family CSS declaration to use a stylised web font first, and fall back to system fonts. This works fine, but my web font is huge ~15MB (Chinese font) and even hosting this on CDN it takes over 5s to load.

The problem with this is that browsers handle the display differently. I think Firefox has the preferred way, which is to use whichever font is available first (system font) and progressively display in the web font when it is ready (loaded).

However, Chrome just tries to use the web font first (as this is listed first in the font-family) and just displays a blank space until the font is ready to render the text.

Is there a way to make Chrome behave the same as Firefox?

EDIT: Add font-family declaration.

font-family: "Noto Sans CJK TC", "Microsoft Yahei", "微软雅黑",
             SimHei, "黑体", STHeiti, "华文黑体", sans-serif;

Upvotes: 3

Views: 10327

Answers (2)

Jehad Ahmad Jaghoub
Jehad Ahmad Jaghoub

Reputation: 1383

the simple way to achieve this to add

@font-face {
    font-display: swap;
}

for more information https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display

Upvotes: 2

Trung Nguyen
Trung Nguyen

Reputation: 529

After reading all the comments, I now have an acceptable solution to progressively loading web fonts.

  1. If possible, use a subset of the font (has all the character/glyphs you intend to use on the page). I had no success trying to create my own subset as the file was huge to start with (font squirrel has a file size limit), but luckily, there was a font I could use from Google's early access fonts (Noto Sans TC). File size went from 15MB to 2MB.
  2. Use gzip compression when uploading to your host (woff2/woff/eot files are already compressed or did not show much filesize reduction). I managed to save 300K doing this.
  3. Set your font-family CSS definitions initially to use web safe fonts.
  4. Define your @font-face definitions as normal and use a font loader with event handling to progressively render fonts (https://github.com/bramstein/fontfaceobserver).
  5. Fontfaceobserver adds a classname to the HTML element so use this for element selections and overwrite existing font-family definitions with loaded fonts (add new font family to the front of existing font families).

There is a slight "pop" when newly loaded font's replace the web safe ones, but at least there is no FOIT (flash of invisible text).

https://www.filamentgroup.com/lab/font-events.html has a good guide on using FontFaceObserver, but couldn't get it to work with their example code. Instead, I used the reference code from the GitHub repo - although I think their wording is wrong/misleading. You should use fontfaceobserver.standalone.js if you don't have a Promise polyfill already implemented.

Upvotes: 3

Related Questions