-
Notifications
You must be signed in to change notification settings - Fork 711
[css-fonts] Reduce layout shift via @font-face descriptor(s) overriding inline spacing #5533
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
Comments
To start, it might be useful to divide the discussion into monospace fonts and variable-width fonts. For monospace fonts, the proposal is straightforward I think. You have a primary font, and you want the fallback font to have an identical advance so it keeps to the grid. So we can just override the advance with a manually-set value, done. (Do we want to center the glyph into the specified advance?) This also prevents fallback to things like emoji fonts from screwing up your monospace grid, at least if we do it right. Variable-width is potentially more difficult:
|
I am not sure that "monospaced" fonts are that simple in an i18n context. For instance, I believe that for CJK, "mono-spaced" is actually "dual-spaced", with full width glyphs being typically 1em wide, and half-spaced glyphs being half that size. Adding a single measurement to all glyphs wouldn't actually work then, would it? |
We've done some manual testing of two versions of adjustment:
(The names are bad but I don't have a better idea...) We found one case with legibility issues: when the font is too bold, reducing the advances may squeeze the characters together, making text hard to read. Other cases seem fine. Anyway, it would be great if someone professional in Persian or Hindi could take a look at those test cases, as I am very unfamiliar with these scripts. As a side note, I'm not sure how much we should be concerned about legibility issues. Our main focus is reducing CLS, so in most cases the overridden text should just appear as a flash. It's an issue only when the web font fails to load, and the fallback font differs from the web font so much that the overridden text becomes hard to read, in which case maybe it's better to use a different fallback font. |
Personally, I'm unconvinced this is a good idea at all. Glyph spacing is an integral part of the font design, and arbitrarily overriding the spacing of glyphs -- not for a specific design intent such as letter-spacing but just to try and match metrics of some other font -- is never likely to look good. To minimize layout shift, specify fallback fonts that have similar metrics to the desired webfont. If they're different enough that layout shift will be a significant problem, then they're also different enough that forcing them to match the intended font will be a distortion. If it's more important to avoid layout shift than to use the designer's "ideal" font, then add a |
An alternative way to try and minimize layout shift if a fallback font is used would be to have a descriptor that allows a scaling factor to be applied to the font (thus improving the metrics-match by scaling the font as a whole, rather than by distorting its glyph widths). |
Here we want both stable layout and the designer's ideal font, so
This sounds like a viable idea. I'll do some testing with it. Btw there's some similarity with #126, just for the record. |
It's possible the desired font will fail to load altogether, and the user will be left looking at the fallback font; it would be sad if they're left with not just a fallback font, but a fallback font with distorted spacing. |
Hmm, scaling the font size does seem to work better... See screenshots: |
The CSS Working Group just discussed The full IRC log of that discussion<Rossen_> Topic: Reduce layout shift via @font-face descriptor(s) overriding inline spacing<Rossen_> github: https://github.com//issues/5533 <chris> q+ to say something that only really works on monospace is kinda suspect <fremy> TabAtkins: we talked about this in the past, we have some updates <Rossen_> q? <Rossen_> ack chris <Zakim> chris, you wanted to say something that only really works on monospace is kinda suspect <fremy> chris: the idea was that to avoid layout shift, you would put values that would update the advance value of the font <fremy> chris: that shift however only works if you have a monospace font <xiaochengh> q+ <jfkthame> q+ <fremy> chris: a multiplier would work <fremy> chris: but that would not work visually <fremy> chris: because the glyphs will overlap each other <fremy> chris: so my thought is that we should instead scale the glyphs <Rossen_> ack xiaochengh <fremy> xiaochengh: there are 3 proposals in the issue <fremy> xiaochengh: 1 add fixed value to the advance <fremy> xiaochengh: 2 scale the advances <jfkthame> q- <fremy> xiaochengh: 3 scale the font-size by some percentage <fremy> xiaochengh: I tested all the 3 <fremy> xiaochengh: and I don't have a strong opinion <fantasai> +1 to everything jfkthame said in the thread <fremy> xiaochengh: I think 3 > 2 >> 1 <fremy> florian: is this meant to be tied to font-display? <fremy> florian: so this only applies after the fallback resolves? <fremy> xiaochengh: we put that in the font descriptor <TabAtkins> q+ <myles> See also: https://github.com//issues/450 <fremy> xiaochengh: so if we fail to load the web font, we use the distorted version of the fallback font <Rossen_> q? <myles> q+ <fremy> TabAtkins: based on JonathanNeal comments <myles> specifically: https://github.com//issues/450#issuecomment-245485065 <fremy> (issue with audio) <fantasai> s/JonathanNeal/jfkthame/ <Rossen_> ack TabAtkins <fremy> TabAtkins: based on the comment scaling the whole thing is similar to the font-size change <fremy> TabAtkins: what was things comment? <fremy> florian: I think that was its preferred option <fantasai> Clearly nobody tried this with Arabic. Doing anything other than scaling that would be seriously broken <fremy> TabAtkins: yeah, then let's agree with his preferred outcome <florian> xiaocheng did try arabic <fremy> TabAtkins: especially since we have similar things already <fremy> xiaochengh: I agree with that <Rossen_> ack myles <fremy> myles: there is an issue I linked to <fremy> myles: and there is one comment in it which I think is useful <fremy> jason list 5 adjustments he would be interested in making <fantasai> myles is referencing https://github.com//issues/450#issuecomment-245485065 I think <fremy> myles: most of properties not descriptors <fremy> myles: so I think the correct solution would not include a descriptor <Rossen_> q? <fremy> myles: so this is one quick fix, but a proper solution would be different I think <fremy> myles: and interact with the 5 properties he mentioned <fremy> myles: and since we probably don't want 2 ways of fixing this <Rossen_> ack fantasai <fremy> myles: I would rather not add this as a stop-gap switch <fremy> fantasai: there are other use cases for this descriptor though <fremy> fantasai: so we could look into this as well <fremy> Rossen_: do you think adding this fix is a step in the wrong direction? <fremy> myles: I think the answer is yes <fremy> myles: because this problem is not urgent <fantasai> s/though/though: because glyphs are often drawn at different actual sizes for the same nominal size, a scale factor could be useful in other cases/ <fremy> myles: so given that, the value of solving one little part is greater than the cost of having two competing solutions in the long term <fremy> Rossen_: so, back to the folks who opened this <fremy> Rossen_: any comment? <myles> s/greater/less/ <fremy> chris: I agree with myles I think <chris> btw we have been trying to solve this since 1997 <fremy> myles: but I want to encourage xiaochengh to look into this more <chris> https://www.w3.org/TR/WD-font-970721#widths <fremy> myles: there is a solution here, but it's not yet there <fremy> xiaochengh: ok, I think I agree with myles <fremy> chris: we had stuff in 1997 about this <fremy> chris: I pated the link in the chat <fremy> jfkthame: we could use the font data and use a data url as the source ^_^ |
According to the discussion, I think this should be marked as a dup of #126 |
This should be discussed along with #126. |
Here's a proposal for the upcoming vf2f discussion:
This is a new descriptor of @font-face that scales the advance width of every glyph of the font face by the given factor. The default value is We have implemented it in Chrome behind a flag, and have observed it working reasonably well. Regarding some previously discussed topics:
|
@chrishtr points out that the use case aimed at is
@xiaochengh can you clarify the relationship between this proposal and #126, and for your proposal can you confirm that the I assume, to use this for reducing layout-shift and specifying an |
+1 to |
No direct relation, at least for the issue that r12a raises in the original post of the thread, but it sits in a related space. This is for the more common case when both the primary and fallback font are visually similar and don't need any major adjustment, but just need slight tweaks to make their advances line up better.
It applies to whatever font the @font-face ends up representing. I didn't really understand your question, but hopefully that answers it sufficiently?
This works entirely thru @font-face, so yes, if you want to adjust a local font for use as a fallback, you'd use
No, this is permanent; if it was temporary, it would cause the very layout shift we're trying to avoid. Your primary font presumably won't have a multiplier, and will display normally; you generally will only apply this to your fallback to make it match the primary more closely, so that when the fallback is swapped out there's as little layout shift as possible. |
This is one of the reasons why it's a good idea to use a new font face that is used just in the fallback path, and that wraps the Regarding timeouts: perhaps as a future feature we could consider adding a timeout parameter to these descriptors or the font face selection algorithm. |
The CSS Working Group just discussed The full IRC log of that discussion<gregwhitworth> Topic: Reduce layout shift via @font-face descriptor(s) overriding inline spacing<chris> github: https://github.com//issues/5533 <gregwhitworth> xiaochengh: we'd like to introduce a new descriptor called advance-override <gregwhitworth> xiaochengh: it's to multiply the advance-width <gregwhitworth> xiaochengh: the intent is to use it to reduce layout shift when switching between fallback and webfonts <gregwhitworth> xiaochengh: it's intended to wrap a fallback font with wrapper to use advanced-override <gregwhitworth> xiaochengh: this is in the same group with ascent-override and line-gap override <gregwhitworth> xiaochengh: there are some considerations with this proposal <chris> advance width described here https://www.w3.org/TR/css-values-3/#ch <gregwhitworth> xiaochengh: the first one is whether to use a property or a descriptor <gregwhitworth> xiaochengh: our consideration is to make things easy to implement and we've confirmed as we've done this behind a flag in Chrome <gregwhitworth> xiaochengh: we want to make it easy for web authors to use it too <fantasai> +1 to making it a descriptor and not a property <gregwhitworth> xiaochengh: a web font provider can provide these in a stylesheet they provide to authors <gregwhitworth> xiaochengh: so we think our proposal achieves all of the goals <gregwhitworth> xiaochengh: font-display cannot really reduce layout shift <chris> q+ to note that advance-width should be advance measure (it is a width for horizontal writing) <gregwhitworth> xiaochengh: the third issue is typography, when we use such override descriptors we expect the legibility of the fallback font to be worsened <gregwhitworth> xiaochengh: we don't think this is unacceptable as it only occurs when a web font fails to load <gregwhitworth> xiaochengh: if the actual fallback font gets unusable means that the fallback font and web font differ too much <gregwhitworth> xiaochengh: there is a similarity between this and letter spacing but they're different things <gregwhitworth> xiaochengh: this is working with the width of the glyphs themselves, so letter-spacing doesn't apply <gregwhitworth> xiaochengh: also happy for name feedback <astearns> ack chris <Zakim> chris, you wanted to note that advance-width should be advance measure (it is a width for horizontal writing) <gregwhitworth> chris: minor point <gregwhitworth> chris: advanced-width is correct for horizontal writing <gregwhitworth> chris: in the units spec, the advance-measure it can be vertical and horizontal <gregwhitworth> fantasai: the problem with that is you may want different numbers with width and height <chris> advance measure described here https://www.w3.org/TR/css-values-3/#ch <gregwhitworth> fantasai: you may not want the same adjustments in both directions <drott> q+ <gregwhitworth> fantasai: if you're typesetting correctly you'll need to ensure you're talking about width or height <myles> q+ <gregwhitworth> chris: I agree with fantasai <gregwhitworth> xiaochengh: this is just for the horizontal width <astearns> ack fantasai <gregwhitworth> xiaochengh: we're using others for vertical for ascent and descent <gregwhitworth> fantasai: I don't think you understood my point as this doesn't have to do with ascent & descent <gregwhitworth> fantasai: depending on how you're typesetting you'll need a different number vertically or horizontally <fantasai> When typesetting horizontally or vertically sideways, need the same number <gregwhitworth> xiaochengh: for the same font, when it's used horizontally & vertically <gregwhitworth> florian: for upright fonts you should probably have two numbers <fantasai> but for vertical writing typeset upright, you will want a different number <gregwhitworth> florian: for that particular problem you should take 2 numbers and the second is optional <astearns> ack drott <fantasai> because that's the height of the glyph you're measuring, not the width of it <gregwhitworth> Domenic: is that required for the specificity of src local for wrapping a web font? <gregwhitworth> fantasai: imagine two fonts Verdana and Times Roman and imagine they look a bit more similar <gregwhitworth> fantasai: you'll notice that Times is very narrow but they're very close in height <gregwhitworth> fantasai: so if you're vertically setting then you're fine <gregwhitworth> Domenic: I was thinking more CJK <gregwhitworth> fantasai: if I'm typesetting vertically (eg: I rotate it) then I'll need to typeset it <astearns> ack myles <gregwhitworth> florian: also the same font may be used in different directions in the same document <gregwhitworth> myles: we've gotten a similar request for similar features that we should be thinking about <gregwhitworth> myles: we're thinking about this in the time of loading to ensure that the fallback looks like the webfont <gregwhitworth> myles: we've looked at this for when a font doesn't support glyphs that the page is asking for and we want to ensure that the fonts look alike <chris> The next topic https://github.com//issues/126 <fantasai> s/need to typeset it/need a different multiplier <gregwhitworth> myles: doing this requires more than just the advance of the font <gregwhitworth> myles: I think it would be good to solve both of these at the same time with the same feature <gregwhitworth> astearns: I agree they're similar <gregwhitworth> astearns: matching the fallback with the webfont you don't know which font will match that font <gregwhitworth> myles: yes each person that has asked for this is willing to spend the time to craft their page to get as close as possible <florian> q+ <myles> https://github.com//issues/126#issuecomment-245708960 <fantasai> s/page/@font-face rules with local/ <astearns> ack florian <drott> florian, https://www.fauxfoundry.com/? <chris> q+ <gregwhitworth> florian: reminds me of a project a while back, something like full greek but you were trying to match the style of greek font even if you only had latin fonts but they used variable fonts to adjust that. Not sure how we apply that idea to this use case <jfkthame> q+ <gregwhitworth> florian: rather than just changing widths <astearns> ack chris <gregwhitworth> chris: yeah, the difference between that and they're changing the glyph outlines to produce a parametized fonts, this proposal is not changing glyphs at all just ensuring the spacing is correct <gregwhitworth> fantasai: this won't work for cursive then <astearns> ack jfkthame <gregwhitworth> chris: I agree, won't work for Mongolian and Arabic <gregwhitworth> jonathan: Seems like what panos was trying to do what Myles was wanting to do <gregwhitworth> jonathan: when fallback happens based on meta attributes it can search for fallback that looks for attributes of the web font <chris> https://www.w3.org/Fonts/Panose/pan2.html <gregwhitworth> jonathan: that's rather different than using a fallback as a given font and behave as much like a particular font <gregwhitworth> myles: yes, what you said is correct <florian> [The project I mentioned earlier is https://www.fauxfoundry.com/ ] <gregwhitworth> myles: the requests we've gotten is not trying to add serifs, like the example florian gave, but the examples are trying to adjust letter-spacing, font-weight (5 props) in the fallback font. And if you're going to use the fallback then bump up the weight <myles> font-weight <myles> font-size <myles> letter-spacing <myles> word-spacing <myles> line-height <chris> Faux Greek foundry https://www.fauxfoundry.com/ <gregwhitworth> myles: the direction I was going there, one possible way - we should solve this problem in multiple ways. We can have a descriptor or we can extend the properties to be fallback aware <leaverou> q+ to say this is starting to sound a lot like the next topic and maybe they should be discussed together? <gregwhitworth> fantasai: I think using font-face is way better given you're describing the font <gregwhitworth> jonathan: very much agree with fantasai on that <chris> by Irene Vlachou & Laurence Penney <fantasai> s/font-face/font-face to tie values to particular font faces/ <gregwhitworth> myles: I'm surprised to hear it although I understand it partly <gregwhitworth> myles: the benefit of the properties is that you get selectors <gregwhitworth> florian: why would you want to select against the element and not the font <gregwhitworth> myles: only request is to consider them both <gregwhitworth> leaverou: I'm hearing a lot of items from the next issue <drott> q+ <gregwhitworth> astearns: I'm thinking of "Yes we should solve this but let's solve all the issues together" <astearns> ack leaverou <Zakim> leaverou, you wanted to say this is starting to sound a lot like the next topic and maybe they should be discussed together? <astearns> ack drott <gregwhitworth> drott: in solving this - do we want to distinguish between another font or what's available locally <gregwhitworth> drott: that's a fast fallback solution or we load a foundry for variable fonts used for fallback that's completely different <gregwhitworth> drott: and it would be required for load <gregwhitworth> astearns: I'd want 1 way to define the override <gregwhitworth> drott: there are two use cases, the more flexible way is a bit wider in scope. <gregwhitworth> fantasai: so they're cursive, you can't letter space them so how do you ensure they're rendered properly if an author sets this <gregwhitworth> myles: would it be the same as the scenario when you use letter-spacing <gregwhitworth> myles: we have a request to ignore letter-spacing when an Arabic font is used <drott> q+ <fantasai> fantasai: that's in the spec <chris> Some arabic fonts do have a spacing axis (variable fonts again) <gregwhitworth> fantasai: that's what we define already for letter-spacing <gregwhitworth> xiaochengh: we tried it on Arabic and we see the width of the characters change and the shaping doesn't look bad <TabAtkins> Lol, Chrome *does* apply letter-spacing to Arabic currently, it just... puts space between teh characters. <TabAtkins> They're still shaped properly for their place in the word. <florian> q+ <TabAtkins> Like kashida-ing without the kashida <chrishtr> q+ <TabAtkins> http://software.hixie.ch/utilities/js/live-dom-viewer/saved/8903 <gregwhitworth> fantasai: I don't think you used a large enough value, in order to avoid rendering at joins they have a small amount of overlap built in <florian> q- <gregwhitworth> fantasai: so to see if it is working or not you'd need a larger range than that tolerance <gregwhitworth> drott: a little bit of adjustment doesn't break them apart <drott> q- <gregwhitworth> chrishtr: if letter-spacing then it seems logical to do the same with this descriptor <chris> q+ <astearns> ack chrishtr <gregwhitworth> chrishtr: the other thought I had was the only other concern would be to apply a different override in each direction <fantasai> s/direction/axis <gregwhitworth> astearns: that was brought up earlier you'll need one for inline and block <gregwhitworth> TabAtkins: no it's inline in both times, just depends on the writing mode <gregwhitworth> fantasai: it will be width/height to the font <astearns> ack chris <myles> https://en.wikipedia.org/wiki/Kashida <gregwhitworth> chris: it's not true to say that those scripts don't have letter-spacing it's that you need to use them to use a longer connection but most fonts don't do that <gregwhitworth> fantasai: it's more complicated than that <gregwhitworth> fantasai: we would say that you don't do this for Mongolian or Arabic and some fonts may do it but most won't <fantasai> s/would// <chris> Arabic text alignment & justification https://www.w3.org/TR/alreq/#h_justification <fantasai> This is specced in css-text-3 <gregwhitworth> astearns: I think we should close off with a general yes, we want to have this advance-override but move to the next issue about how to define it <gregwhitworth> myles: is it going to be a length? <gregwhitworth> xiaochengh: it's a percentage <gregwhitworth> chris: it's a multiplier <gregwhitworth> TabAtkins: it's going to be the best overall solution that works the most consistently |
Just wanted to note, the proposed name was |
Looks like the resolution may not have been recorded, but there was a resolution 3 days ago to go ahead and add the feature as a font-face descriptor with the design generally along the lines of what Xiaocheng proposed in this issue. |
The resolution was recorded in the official minutes https://lists.w3.org/Archives/Public/www-style/2021Feb/0015.html just seems like the IRC bot didn't catch it. |
Agenda+ to ask if we should close this issue as no-change, now that we have |
+1 to closing the issue. |
+1 |
The CSS Working Group just discussed
The full IRC log of that discussion<Rossen_> topic: Reduce layout shift via @font-face descriptor(s) overriding inline spacing<Rossen_> github: https://github.com//issues/5533 <chris> Yes this one should be closed <TabAtkins> TabAtkins: Now that we ahve 'size-adjust', can we close this issue? Chris Harrelson and Chris Lilley both say yes, close it. <jfkthame> +1 to closing <chrishtr> Xiaocheng is also happy to close it. <TabAtkins> RESOLVED: the issue is resolved |
In #4792, we agreed to add @font-face descriptors to override ascent, descent and line gap of a font, which allows us to match the line height metrics between fallback and primary font, and hence, reduce layout shift.
In #4792 (comment) I also proposed
advance-override
to override the inline spacing and further reduce layout shift. The proposal still has several problems and hence remains under discussion.So I opened this issue to specifically discuss if we should add new descriptor(s) to @font-face to override the inline spacing for matching text widths and reducing layout shift; And if we should, how should the new descriptor(s) work.
The text was updated successfully, but these errors were encountered: