You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, we don't have any easy & sound way to eliminate FOIT & layout shifts caused by web fonts:
font-display: optional elimintes layout shifts and FOIT, but at the cost that the web font may not be used, which limits its usage
Other font-display values do not reduce layout shifts at all
size-adjust descriptor only reduces the layout shift but can't guarantee 0 CLS, and there might still be a FOIT. It's also complicated to use since we need to find out the correct value.
I'm proposing adding a new keyword to the font-display descriptor, tentative named font-display: critical, which:
Turns the @font-face a critical subresource of the style sheet, and hence makes it block the load event of the style sheet
Makes UA start loading such a @font-face eagerly; other font faces are still loaded lazily when used
In this way, as long as the @font-face is defined in a render-blocking style sheet (which everyone knows about but hadn't been specified until recently), then it will block the first render of the document, and hence eliminate FOIT / layout shifts.
This feature is supposed to be used on web fonts that are truly critical, so that developers want to eliminate FOIT / CLS at a great cost of delaying rendering. It will be footgun-ish and shouldn't be used arbitrarily.
Use cases
Basic usage:
<head><style>@font-face {
font-family: my-font;
font-display: critical;
src:url(/my-font.ttf);
}
body { font-family: my-font; }
</style></head><body>
Text in my-font with absolutely no FOIT / CLS
</body>
There's also a particular use case I'd like to support: making a 3rd party web font render-blocking without knowing the font url.
Developer page:
<head><linkrel=stylesheethref="https://3p-fonts.com/cool-font.css?critical=yes"><style>body { font-family: cool-font; }</style></head><body>
Text in cool-font with absolutely no FOIT / CLS
</body>
@font-face {
font-family: cool-font;
font-display: critical;
/* url is maintained by 3p-fonts.com. May change at any time; may even be generated. *//* Developers shouldn't preload this url or inline this style sheet. */src:url(/some-random-hash-123654ABCFED-or-whatever.ttf);
}
Possible discussions
Q: How about preloading the font?
A: Preloading just makes it less likely to cause FOIT / layout shifts, but there's no guarantee. And it doesn't work for the 3rd party web font use case.
Q: How about adding blocking=render to the font preload <link> to block rendering until the preload finishes?
A: Besides not working for 3rd-party web fonts, there are many issues with making preload explicitly interact with rendering, so we decided to remove blocking=render from preload. See more discussions at
Q: This further blocks rendering on a subsequent load, which is bad for loading performance
A: We can't fully eliminate subsequent loading behavior, since we must use external style sheet for 3p web fonts. However, there are ways to alleviate this by starting the font loading as early as possible (see below):
UA can use a preload scanner that not only preloads the external style sheet
UA can also use a preload scanner to scan the external style sheet response to preload the font
The external style sheet response can also have a Link header that preloads the font
Q: Why making it a font-display keyword?
A: This provides an even stronger alternative than font-display: block. So it doesn't make much sense to be a standalone descriptor and then interact with the other font-display values. That's also the reason why its font display timeline is the same as font-display: block, though it's mainly for spec completeness -- if we ever need to use such a font while it's still pending, it's likely a misuse.
Q: What if it blocks rendering indefinitely?
A: Render-blocking stylesheets and scripts can already block rendering indefinitely (or until the UA gives up), so it's not more footgun-ish than existing render-blocking things. And it allows developers to achieve a tradeoff that's hard to achieve before.
Possible blockers
"CSS critical subresource" seems very under-specified at the moment (Define which subresources block the DOM load event #1088). But I guess we can just say "critical subresources should at least include font-display: critical font faces" without having to fully define what other critical subresources are.
Currently, we don't have any easy & sound way to eliminate FOIT & layout shifts caused by web fonts:
font-display: optionalelimintes layout shifts and FOIT, but at the cost that the web font may not be used, which limits its usagefont-displayvalues do not reduce layout shifts at allsize-adjustdescriptor only reduces the layout shift but can't guarantee 0 CLS, and there might still be a FOIT. It's also complicated to use since we need to find out the correct value.I'm proposing adding a new keyword to the
font-displaydescriptor, tentative namedfont-display: critical, which:@font-facea critical subresource of the style sheet, and hence makes it block theloadevent of the style sheet@font-faceeagerly; other font faces are still loaded lazily when usedfont-display: blockIn this way, as long as the
@font-faceis defined in a render-blocking style sheet (which everyone knows about but hadn't been specified until recently), then it will block the first render of the document, and hence eliminate FOIT / layout shifts.This feature is supposed to be used on web fonts that are truly critical, so that developers want to eliminate FOIT / CLS at a great cost of delaying rendering. It will be footgun-ish and shouldn't be used arbitrarily.
Use cases
Basic usage:
There's also a particular use case I'd like to support: making a 3rd party web font render-blocking without knowing the font url.
Developer page:
https://3p-fonts.com/cool-font.css?critical=yes:
Possible discussions
blocking=renderto the font preload<link>to block rendering until the preload finishes?blocking=renderfrom preload. See more discussions atblockingattribute on apreloadlink whatwg/html#7896Linkheader that preloads the fontfont-displaykeyword?font-display: block. So it doesn't make much sense to be a standalone descriptor and then interact with the otherfont-displayvalues. That's also the reason why its font display timeline is the same asfont-display: block, though it's mainly for spec completeness -- if we ever need to use such a font while it's still pending, it's likely a misuse.Possible blockers
font-display: criticalfont faces" without having to fully define what other critical subresources are.@tabatkins @chrishtr