This article is written by He Wenli, front-end development engineer of 360qi Dance company, and a member of W3C CSS working group

The phenomenon of

When browsing websites that use custom fonts, or using @font-face in development, it’s common to see that the page structure and images are out, but the text area is blank. This phenomenon is called FOIT (Flash Of Invisible Text).

why

In general, we use the @font-face rule definition to make browser loads use third-party fonts. These rules, written in the CSS file, must wait until the file has been downloaded and parsed before the browser can start downloading the font file. To actually trigger a font file download, some conditions must be met. According to this article from Zach Leatherman, to trigger a font download, the following conditions must be met:

  • legal@font-faceRules, and the current browser needs to supportsrcThe format given in the list
  • A node is used in the document@font-faceIn the samefont-family
  • Use this in Webkit and Blink enginesfont-familyCannot be empty
  • if@font-faceSpecified in theunicode-range, the text content must also fall within the specified Unicode range

When all of the above conditions are met, the browser will start downloading the font file, which means that the browser will not only have to parse the CSS content, but also the page content to decide whether to download the font. When the browser starts downloading the font, all the text using the font family is hidden, resulting in blank text on the page.

To solve

The FONT display property in CSS Fonts Module Level 3 and the CSS Font Loading API standard are among the W3C standards for Fonts.

font-display

Font display is added to CSS Fonts Module Level 3. Most browsers already support this property.

Font display provides a solution to this problem at the CSS level, providing five properties:

  • Auto: uses the default behavior of the browser.
  • Block: The browser first replaces the text on the page with invisible text and waits for the font to load before displaying it.
  • Swap: If the set font is not available, the browser will display it in the standby font first, and replace the standby font when the set font is loaded.
  • Fallback:swapProperty values are roughly the same in behavior, but the browser sets a loading time limit for a font. If the loading time is greater than this limit, the font will not be displayed instead of the alternate font. Webkit and Firefox set this time to 3s;
  • Optional: When using this property, if the font is not loaded within the specified time limit, the current page will always use the alternate font and the font will continue to load in the background so that the next time you browse the page, you can use the new font directly.

CSS Font Loading API

In addition to solving the problem at the CSS level, the CSS Font Loading API (2) also provides a solution at the JavaScript level. By listening for the loading event, we can achieve the effect of the swap property value in the CSS by replacing the class after the font is loaded.

Browser support is also mediocre

FontFace interface support

FontFaceSet interface support

The standard mainly provides the FontFace interface for loading fonts, and the Document. fonts object is a FontFaceSet interface, which is a set of FontFaces and manages the state of all fonts on the page.

FontFace accepts three parameters: font family name, font resource location, and (optional) font Settings.

First, to load the font in JavaScript, we need to new a FontFace and add it to the global FontFaceSet:

const Aclonica = new FontFace('Aclonica'.'url(./Aclonica.ttf)');
// Add to the global FontFaceSet
document.fonts.add(Aclonica);
Copy the code

Step 2: Start loading by calling FontFace’s load method, which returns a Promise. When our font is finished loading, we can replace it with a new font by changing the class.

Aclonica.load().then((a)= > {
    // When the font is loaded, we can replace the default font by replacing class
    // The logic here can also be your font rendering strategy
    document.body.classList.add('use-aclonica');
})
Copy the code
.use-aclonica {
    font-family: Aclonica;
}
Copy the code

Not perfect

After we optimized it in the above way, the FOIT phenomenon was eliminated, but the actual effect looked like this:

We find that the page inevitably flashes after the font is loaded. This is due to the visual effect that the alternate font is too different from the defined font shape, which is also known as FOUT (Flash Of Unstyled Text). It’s obviously not a great experience for the user reading the article.

summary

CSS Fonts Module and CSS Font Loading API both give front-end Fonts more capabilities in both rendering and control. As we further study the specification, we believe that there will be more solutions to Font Loading and rendering problems.

Text links in

(1) www.zachleat.com/web/compreh…

(2) drafts.csswg.org/css-font-lo…

Thank you

Thanks to Teacher Li Songfeng for his suggestions