Open KenjiBaheux opened 9 years ago
@KenjiBaheux yeah that's pretty magical.
Does this block just paint or layout as well? For example can I query offsetWidth of an element which doesn't have a loaded font yet?
Re: Houdini, nothing in the spec w.r.t. holding paint at the moment, however we've had discussions regarding when to paint (I.e. if blocking is a reasonable option) in addition to blocking layout. Element optionality and asynchronous in-flow elements (if we end up doing them) will need similar ideas.
If we had some kind of paint blocking primitive then font-rendering could be implemented entirely as a user-land property on top of Houdini.
Do we have anything else which can block rendering on the page? For example:
Are there things that we should allow blocking rendering? For example:
Ian
@bfgeek Before a font loads, we're either rendering with a fallback, or with some sort of "default" metrics (depending on whether we're in the block or swap period). So nothing is blocked; we can paint immediately, query things immediately, etc. (In other words, during the "block" period, you fallback to an invisible default font which has no glyphs.)
@bfgeek @tabatkins 's description is more accurate.
Perhaps, "custom paint" and "custom layout" are more relevant then?
If we can explain all font-rendering
behaviors via custom paint and custom layout callbacks, can we consider this issue resolved?
Naively, I imagine that it can be achieved through a combination of:
Let me try a few
For an element whose style is set with font-rendering: optional
:
Have a custom layout callback where:
For an element whose style is set with font-rendering: block infinite
:
Have a custom paint callback where:
For an element whose style is set with font-rendering: block 0s swap 500ms
:
Have a custom layout callback where:
Have a custom paint callback
How does that sound?
cc/ @igrigorik
@KenjiBaheux I think that's spot on. My only nitpick would be with the last 500ms timer logic:
set a race between a (500ms - performance.now()) timeout and a Font Loading check() to find out if the desired font is ready before timer elapsed...
That is, I think we should think of the specified "500ms" timer as counting from navigationStart, instead of requestStart, because requestStart is a moving target and hard to reason about.
That is, I think we should think of the specified "500ms" timer as counting from navigationStart, instead of requestStart, because requestStart is a moving target and hard to reason about.
Is that consistent with what browsers actually do? My spec currently dictates that the timer starts at requestStart, because it doesn't seem to make much sense for a font that isn't used on load to have its timer already-expired when it is finally invoked.
@tabatkins consistent with respect to what? I think both start times are valid (navStart, requestStart) and have their respective use cases. That said, I think navigationStart is what developers would expect/want in the context of optimizing rendering behavior of the page...
The problem with fetchStart is that you actually have no idea when the request will start, so "3s" from fetchStart is actually 3s + unknown-fetch-start-delay
, where the unknown delay can be easily measured in seconds -- e.g. style calc is blocked on slow response of a script, other css file, etc. As such, this is not terribly useful: an optional
font may still be blocked for some time; all timers have an unknown value added to them. If my goal is to deliver a reliable 1000ms render (with desired font, or fallback), I can't do that with font-rendering that uses fetchStart, since I don't know when fetchStart will fire.
Making font load behavior depend on document load time, so that a timer can expire before you ever even attempt to load the font file doesn't sound useful. If you think there is a use-case, coudl you elaborate?
You seem to be thinking about the difference in time between "I've activated the style that applies the font" and "the font load is started", but it's actually the difference in time between "the page is loaded" and "the font load is started". If I only use a particular font on error messages, and the user doesn't cause an error message until they've spent a minute or two on the site, that's 100s or more of difference between the two times.
You're right, the timer business is complicated.
My primary goal is to ensure that we enable developers to deliver the fastest possible experience in their application. In the case of text-rendering, this means giving them control over which text rendering strategy is chosen when the text is first ready to paint - i.e. should the UA paint it now and swap in the font, should the UA block and paint later, or should it paint with whatever is available and leave it. This decision / property is independent of any timers.
Some concrete applications of this are:
Stepping back, perhaps the timer semantics can be separated from the control of the chosen font-rendering strategy? As in, block / swap / optional
are properties on the text, whereas timer is a property of the font? Hand~wavy example...
@font-face {
font-family: 'Open Sans';
...
font-timeout: 3s;
}
.content { font-rendering: swap; font-family: Open Sans; }
.other { font-rendering: block; font-family Open Sans; }
The font-rendering
controls which strategy is chosen when text is first ready to paint, and timeout is controlled by the @font-face property? This model has its limitations as well, but it feels "more right"?
On Wed, Apr 8, 2015 at 1:18 PM, Tab Atkins Jr. jackalmage@gmail.com wrote: (www-style) In the call today, we agreed to initially give the spec only the keyword values, with an issue discussing whether or not to allow explicit timeouts.
Hmm, I think this is effectively what I'm proposing above, except that font-rendering applies to @font-face as well.. perhaps that's unnecessary?
Why can't the timeout be done in js? We set a timer to change the style...
What do y'all think about a shared google doc for "can font rendering be done with houdini?" Its easier to collaborate on a proposal in that format, ask questions, share around to other people, than with a centithread.
I think the FontLoader API + setTimeout is enough for JS to deal with this. +1 to discussing it in a doc.
FontLoader API and setTimeout being enough is missing the point.
https://lists.w3.org/Archives/Public/www-style/2014Oct/0505.html
Why can't the timeout be done in js?
Because you don't know when the timer started? It starts when we first attempt to use the font. To get the same behavior, you have to not use the font at all withing your CSS at first, and instead invert your design so that the element pings some observer about what font it needs when it first knows it's going to render (somehow, perhaps a more explicit "display me" API, which means you're avoiding use of the 'display' property too...).
In general, all of this stuff can be done with the Font Loading API, to some degree of fidelity. It's not trivial, but it's doable. However, attempting to argue that this means we don't need anything in CSS is completely wrong-headed, for several reasons:
The CSS font-rendering proposal is an attempt to explain the bit of magic that goes on around web font rendering in browsers:
A discussion around the adequacy of the name "font-rendering" lead to the realization that we have a hard time identifying/naming the underlying system involved here. This suggests that CSS font-rendering might not be ambitious enough or might not explain the actual magic but a specific manifestation of it. I think this is worth investigating in parallel with making progress on the proposal and adjust as we learn more.
Relation to Houdini to/ @shans @bfgeek
To start, we should find out if Houdini (bedrock for CSS) would impact this proposal, otherwise we run the risk of turning CSS font-rendering into The Magic Trick That Fooled Houdini ಠ_ಠ
Is the CSS font-rendering use case (a specific manifestation of the magic that goes into holding paint) in scope for Houdini? Anything started in this area?
CSS font-rendering example
cc/ @natduca @igrigorik @tabatkins