Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-fonts] More intuitive version of preload + font-display optional #5924

Closed
xiaochengh opened this issue Feb 3, 2021 · 6 comments
Closed

Comments

@xiaochengh
Copy link
Contributor

When a web author doesn't want to pay any CLS for web fonts, but still want the font to be used with a big enough chance, there's a trick of combining (example example):

  • A preload of the font file (<link rel=preload>)
  • Setting the font-display descriptor value to optional

It makes the web font acts similar to a local font that:

  • If the font loads fast enough, then we never use fallback fonts, which is similar to a successful load of a local font
  • If the font loads slow to fails, then we end up using fallback, which is similar to a failed load of a local font

However, the trick is pretty unintuitive. Preload indicates that the font is important, yet font-display: optional means the font is not so important. It can be very confusing (example).

So I'm filing this issue to investigate a more intuitive version.


Idea: A new font-display value that does the same? As soon as we see it in a stylesheet, we kick off a preload of the font, and block rendering before the preload finishes or a timeout (e.g., 50ms); And the font enters the failure font display period as long as any fallback has been used.

Also note that in Chrome, we've already implemented this behavior when preloading and font-display: optional are used together.

@tabatkins
Copy link
Member

The problem with trying to tie this to any font-display value is that it delays the point when we can paint even further, to when the stylesheet is encountered and loaded. Preloading, by definition, is about as early as possible for indicating that a load should be started.

If we don't adjust the preload period to account for the stylesheet's own load delay, then trying to rely on this trick becomes very fraught - it's likely to work on local testing and fail in the wild. If we do adjust the preload period, then we're more likely to either significantly delay rendering, or cause a flash of restyled text if we've already started rendering.

@xiaochengh
Copy link
Contributor Author

If we do adjust the preload period, then we're more likely to either significantly delay rendering,

So there's a timeout to make sure we don't significantly delay rendering.

or cause a flash of restyled text if we've already started rendering.

We won't get any FOUT or layout jank, because as long as any fallback has been used, the web font enters the failure display period and won't be swapped in.

@tabatkins
Copy link
Member

So then if we have a timeout and ensure we don't get FOUT, that runs directly into my later concern that this is very easy to have work on your local machine and fail in prod, when the load times are higher.

(Vs an explicit preload, which is almost certain to be seen early enough even on slow connections. The font still might not load in time on prod, but that's a reasonable and acceptable failure at that point.)

@tabatkins
Copy link
Member

(If it turns out that my concerns are unfounded, and in fact this sort of delay is completely fine in practice, that would be a welcome surprise, fwiw. I'm not trying to block anything easier here.)

@noamr
Copy link
Collaborator

noamr commented May 7, 2022

The problem with relying on preload in font rendering (as described in whatwg/html#7896), is that it ties together fetching and font processing. Preloads are supposed to be a resource hint, something that changes the loading order, not something that affects rendering. By adding render semantics to preload, especially as the only way to block rendering on a particular type of resource like in the case of fonts, we make preloads into a mixed bag of features.

I believe that if a style can be declared as explicitly render-blocking (<link rel=stylesheet blocking=render>), then that style should be the one to carry on the chain of blocking the render, by declaring a particular font or image resource as render-blocking (imported styles carry the chain implicitly).

I agree that preloading those fonts first is a best practice, but I think that what it warrants is a warning rather than disabling: allow people to render-block on fonts explicitly (if the containing style is render-blocking) but put a warning in the dev-tools console if that font has not been preloaded, encouraging to preload the font in addition to the block.

Also, this leaves an opportunity for user-agents to speculatively parse render-blocking styles to find render-blocking fonts and preload them, similar to how modulepreload is designed to work.

I suggest that in the future we should enable the same for images in some form, perhaps similar to how we're going to tackle CORS settings in CSS images.

What I want to avoid is making the render-blocking chain something that relies on disparate elements/headers in the same document rather than a clear chain of hrefs.

/cc @yoavweiss

@xiaochengh
Copy link
Contributor Author

I'll close this issue as it's superceded by #7271.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants