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

font-desirability: optional, progressive, mandatory #5

Merged
merged 14 commits into from
Oct 27, 2014

Conversation

igrigorik
Copy link
Contributor

  • optional, progressive, mandatory rendering strategies
  • added CSS highlighting, fixed examples, other minor stuff

- wording improvements
- replace "readily available" with "first text-paint-time"
- fix "timeout" -> "font-timeout" in examples
- add CSS highlighting
Reworked font-desirability to provide hooks for first paint rendering strategy.

closes #1, #4
@igrigorik igrigorik changed the title few small updates font-desirability: optional, progressive, mandatory Sep 25, 2014
@tabatkins
Copy link

I don't understand the point of splitting "optional" into "optional" and "progressive". In a private email thread, you hinted that this was an attempt to solve the "you might have the font, but it might still be tens of milliseconds away" problem, but I don't see how it has anything to do with that. As written, it seems to just provide the exact functionality already given by using a mix of url() and local() functions in src.

css-font-timeout
================
A proposal for CSS to let web developers control font timeout.
## css-font-timeout

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you converting this to an h2, and lowering all the other headings a level as well?

@igrigorik
Copy link
Contributor Author

I don't understand the point of splitting "optional" into "optional" and "progressive". In a private email thread, you hinted that this was an attempt to solve the "you might have the font, but it might still be tens of milliseconds away" problem, but I don't see how it has anything to do with that. As written, it seems to just provide the exact functionality already given by using a mix of url() and local() functions in src.

The key observation here is that there is no way for a developer to guess the right timeout value if their goal is to deliver a consistent+optimal first text-render experience: some cache and local() lookups can take north of 100 milliseconds; network fetches might take anywhere from low tens to thousands of milliseconds; different browsers on different hardware will parse and layout page content with different speeds. It's a crapshoot.

That said, the actual problem we're trying to address is: at some point the browser is ready to layout and render content that includes text pixels, what strategy should it pick? The font-timeout value is irrelevant here, what's important is whether (and which) font is available to render the pixels - i.e. should it use fallback if desired font request is outstanding, or should it block text rendering... That's what font-desirability allows us to specify: it defines the path the browser should take at the earliest point when its ready to paint the text, irrespective of the timing or the status of the font request.

With that in mind, optional vs progressive:

  • optional: if desired font is not (yet) available, use fallback, don't rerender (e.g. avoid expensive reflow or jarring content flashes)
  • progressive: if desired font is not (yet) available, use fallback, rerender unless font-timeout has expired.

Note that local() vs url() is orthogonal to this discussion - fetching font from disk might take arbitrarily long, same for cache lookup or network request initiated via url().

@tabatkins
Copy link

Oh, I see! If the browser knows it needs a font, but it doesn't yet need it to actually lay anything out, then an "optional" value would let it be used; if it needs a font but needs to lay out before the font arrives, "optional" will have it use the fallback instead, while "progressive" makes it swap out for the desired font when it arrives.

These names need some work, in that case. These are really two orthogonal concerns:

  1. Should you block rendering until the font arrives?
  2. Should you swap out the font when it arrives, if you'd already started rendering with a fallback?

Because the first covers the second, it looks like it can be arranged into three values, but I think that obscures things. I prefer something like:

font-timeout: <time> swap?
font-optional: optional | mandatory

The presence/absence of the "swap" keyword controls what happens at the end of the timeout (question 2). The 'font-optional' property controls what happens when the browser first discovers it needs a font it doesn't have (question 1).

Also, it uses easier-to-spell words. ^_^ That's not a minor thing; "desirability" trips up my fingers every time I try to type it, and I'm an excellent speller; it's just a clumsy word to type.

(Regarding your last paragraph, I was pretty sure that local/url was indeed not what was being covered here, but the text you're proposing doesn't make that clear.)

@igrigorik
Copy link
Contributor Author

You're right, I'm conflating orthogonal concerns. But, it seems like font-timeout + swap does as well because font request end-time is not always equal to font timeout.

We have three different conditions / points in time to consider:

  1. policy for when browser is ready to render chunk of document with text in it
  2. policy for when font has finished loading
  3. policy for when font request timeout is reached

What if we map the three to these properties:

font-rendering: optional | mandatory  (controls #1)
font-optional: swap | fallback        (controls #2 if #1 is set to 'optional', otherwise no-op)
font-timeout: <time>                  (controls #3)

Default (Chrome) behavior is: font-rendering: mandatory + font-timeout: 3s. However, I can now also declare font-rendering: optional, and choose between (a) use fallback don't rerender (font-optional: fallback), or (b) use fallback and swap unless timeout has been reached (font-optional: swap).

font-optional is only applicable if font-rendering is set to optional, and default value is swap - i.e. render immediately with fallback and rerender with desired font later, unless font-timeout is reached.

WDYT?

@tabatkins
Copy link

I still think this is overcomplicated, but I agree that my previous carving up was suboptimal. Let's revisit the use-cases:

  1. This font is required for the page to look right. Don't even bother rendering with a fallback. (But if the timeout expires, oh well, show something.)
  2. This font is desirable for the page to look right. Feel free to render with a fallback font at first, but use my desired font when it comes in. (But if the timeout expires, give up, because it's too disruptive to swap in a new font when they're already deep into reading a page.)
  3. This font is decorative and optional for the page to look right. Use it if you can get it "quickly enough", but otherwise just give up; flashing to a new font is worse than just sticking with a fallback.

Is this all of them? Is there anything else?

Given these three, I think we can simplify significantly. The difference between 1 and 2 is what to do before the font loads/the timeout expires: show nothing or show a fallback. The difference between 2 and 3 is that 3 sets the timeout value to "when you start actually rendering the affected text".

So, let's try just handling those directly:

font-rendering: optional | swap <time> | mandatory <time>

This covers the three use-cases directly, and only exposes a timeout for the cases that need it. If we really feel like it, we can pull the timeout out into a separate descriptor, even though it doesn't apply to optional, but there's no cascade concern here (our usual criteria for whether to split something out into a separate property or not), so it's pretty much purely an aesthetic concern.

Importantly, this also means that authors don't have to think about combinations and what different properties do in difference circumstances. They just have three easy-to-explain cases, and can choose which one they want.

@igrigorik
Copy link
Contributor Author

@tabatkins I like it! Much simpler, and covers all the necessary cases.

Updated the pull, PTAL: https://github.com/igrigorik/css-font-timeout/blob/patch-1/README.md

@tabatkins
Copy link

Oops, I missed marking the s as optional. They should be omittable, and default to, I dunno, 3s?

@igrigorik
Copy link
Contributor Author

Ah, right, good call. Updated to use 3s as default.

KenjiBaheux added a commit that referenced this pull request Oct 27, 2014
font-desirability: optional, progressive, mandatory
@KenjiBaheux KenjiBaheux merged commit 78ddf14 into KenjiBaheux:master Oct 27, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants