[go: nahoru, domu]

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] Don't require browsers to always match every generic font family to a concrete font family #4442

Closed
litherum opened this issue Oct 22, 2019 · 28 comments
Assignees
Labels
css-fonts-4 Current Work i18n-tracker Group bringing to attention of Internationalization, or tracked by i18n but not needing response.

Comments

@litherum
Copy link
Contributor
litherum commented Oct 22, 2019

CSS Fonts currently says:

Each generic font family must always map to at least one matched font face.

I'd like to propose deleting this sentence because it does not accomplish its goal, nor could it ever accomplish its goal. This is because browsers are free to map the generic font families to any concrete font or font stack, regardless of that font's Unicode coverage. There's no guarantee that, when an author specifies a generic font family, that the concrete font can actually be used for any of the content on the page. Indeed, the mapped font could be a font which supports 0 characters.

I'd also like to add a sentence encouraging authors to use generic font families in their font-family lists. This provides a signal for what kind of font the author desires, regardless of whether or not it actually ends up being used. WebKit (and other browsers too?) will consider this kind of signal when we "fall off the end" of the font-family list and have to pick a font for the content but can't use any of the fonts in the specified list.

I'm not actually proposing any behavior change in browsers. The difference between fantasy mapping to a font that supports 0 characters, and fantasy not mapping to any font, is untestable. Untestable things shouldn't be normative in specs. EDIT: This is false. See #4442 (comment)

This has implications for the new ui-serif, ui-monospaced, and ui-rounded font families. We resolved that these shouldn't map to any concrete fonts on platforms that don't have an appropriate UI font for them. Therefore, under the current text, they can't be generic font families, and should instead be a new class of fonts. I don't think it's valuable to have two distinct classes of fonts in the spec when their difference is meaningless and untestable.

@kojiishi
Copy link
Contributor

+1

This provides a signal for what kind of font the author desires, regardless of whether or not it actually ends up being used. WebKit (and other browsers too?) will consider this kind of signal when we "fall off the end" of the font-family list and have to pick a font for the content but can't use any of the fonts in the specified list.

Yeah, Blink wishes to do this too.

@svgeesus svgeesus added the css-fonts-4 Current Work label Oct 28, 2019
@svgeesus
Copy link
Contributor

I'm in favor of deleting that sentence.

I'm in favor of encouraging authors to use generics, and specifically motivating this (beyond general "it is good to do so") by saying this affects browser behavior when the end of the font stack is reached.

@tabatkins
Copy link
Member

WebKit (and other browsers too?) will consider this kind of signal when we "fall off the end" of the font-family list and have to pick a font for the content but can't use any of the fonts in the specified list.

Can you elaborate on this? I don't understand what you mean - are you saying that if the author puts serif at the end of their stack, but they use a character not mapped by the font that WebKit assigns to serif, it'll still influence what additional fonts WebKit looks for to find a mapping for the character?

@frivoal
Copy link
Collaborator
frivoal commented Oct 29, 2019

It was my understanding that generic families always matched (even if they had not usefully distinct character to provide), and therefore that it made no sense to put any fallback after a generic font family, as it would never be reached. However, It doesn't seem to actually be true, and it seems that when a generic font family does not provide a glyph for a particular unicode code point, browsers do allow fallback to font families specified after it in font-family.

I can think of a few possible variants of what the "Each generic font family must always map to at least one matched font face." might mean:

  1. It means nothing, generic families behave like any other font family: they may be composites of multiple actual font faces in order to cover a broad unicode range, and when they don't match for a given character, we fallback to whatever is next in the specified font stack, and eventually to the system fallback if nothing matches.
  2. It means that generic font families include the "fall off the end" fallback, and always match. Due to limitations on what's available on the system, not all components of a generic family will be usefully differentiated to match the requested style, and multiple generic families may share some font faces in their stack, but regardless, they always match, even if it is just to show a tofu glyph. Listing a font (generic or not) after a generic one in font-family never has any effect.
  3. Generic families, like any other family, may or may not have glyphs for the characters at hand, and when they don't, fonts listed after them are used as fallbacks. They may possibly contain no glyph at all, depending on what's available on the system, but even in that case, if no specified font family prior to in in the font stack has a glyph for U+0020, the (empty) generic family still counts as the "first available font", and this impacts things like the line-height or the size of the font relative units.

I think variant 3 is not useful, and we should not do that.

I (and at least some other people as well, given the recent discussions around this topic) thought that variant 2 was the specified (and implemented behavior). It does not seem to be the implemented behavior. As far as specs go, they all seem somewhat ambiguous, and the wording has evolved between css2, fonts-3, and fonts-4. The older wordings (see css2 for example) seem to me to be more strongly calling for behavior 2 than the newer ones, but none of them is 100% clear cut.

Variant 1 is explicitly the one we said we wanted for system-ui and the like. For other generic families, it seems to be what browsers actually implement, and may be a good idea: I always assumed that writing @font-face { font-family: "micho fallback"; src: …; } html {font-family: serif, "mincho fallback"; } was not a thing I could do in order to supply a web-font based fallback for systems that didn't have a Mincho font, while leaving those that do use the system font. But it seems it's actually possible, and it is very useful, so I support behavior 1 for all generic font families.

Picking behavior 1 also makes questions like the one I raised in #4425 largely go away, as behavior 2 was the assumption underlying that question.

are you saying that if the author puts serif at the end of their stack, but they use a character not mapped by the font that WebKit assigns to serif, it'll still influence what additional fonts WebKit looks for to find a mapping for the character?

That question only makes sense if we go for behavior 1 (or 3), because with behavior 2, the fallback is part of the generic font family itself, not something that happens after it.

If we do go with behavior 1, in order to set author's expectations it would be useful to specify whether:

  • the fallback must be independent of the specified font stack
  • the fallback may be influenced by the last font in the specified font stack if it is generic
  • the fallback may be influenced by the last generic font in the specified font stack, even if it is followed by non generics
  • the fallback may be influenced by [... some other specific thing ...]
  • the fallback may be influenced by the specified font stack in arbitrary ways up to the UA

@kojiishi
Copy link
Contributor

WebKit (and other browsers too?) will consider this kind of signal when we "fall off the end" of the font-family list and have to pick a font for the content but can't use any of the fonts in the specified list.

Can you elaborate on this? I don't understand what you mean - are you saying that if the author puts serif at the end of their stack, but they use a character not mapped by the font that WebKit assigns to serif, it'll still influence what additional fonts WebKit looks for to find a mapping for the character?

Our impl is very similar to what @litherum explained; generic families (except system-ui) are mapped to single font, so it is not guaranteed to match. We even allow users to change the mapping.

Regardless generic families are used or not, we have a logic to run when all specified families are exhausted and still the glyph is missing. This logic doesn't have a good name, I think this is what @litherum called "fall off the end". I usually call it "system fallback" but this isn't probably a common name, I think you called it "last resort font" (in broad sense, not the "LastResort" font unicode.org provides), this is probably more common.

A discussion we had before was that, during this "fall off the end or system fallback or last resort font in broad sense" process, we may find multiple candidates, and the idea was that generic families in the font-family property can provide a hint to which candidates we want to choose. font-weight or font-style can also provide more hints.

Back to the original discussion, I don't have strong opinion on whether the spec should encourage authors to use generic families or not, I'm fine with it or without it, but I agree with @litherum that more hints from authors could improve our font choice.

@kojiishi
Copy link
Contributor

/cc @drott

@litherum
Copy link
Contributor Author
litherum commented Oct 29, 2019

@tabatkins

are you saying that if the author puts serif at the end of their stack, but they use a character not mapped by the font that WebKit assigns to serif, it'll still influence what additional fonts WebKit looks for to find a mapping for the character?

Yes, in some situations.

@litherum
Copy link
Contributor Author

@frivoal What's the difference between option 1 and 3? They sound the same to me.

@frivoal
Copy link
Collaborator
frivoal commented Oct 29, 2019

Let's say your font stack is: p {font-family: fantasy, Helvetica; } on a system which has chosen not to map fantasy to anything (or equivalently, to a conceptual font with no glyphs in it).
You try to display <p>hello world</p> with it. If you don't like the idea of mapping fantasy to nothing, replace with fangsong with no loss of generality.

If we've ruled out option 2 (which disallows falling back from a generic family and requires that it maps to something for all glyphs), the logical thing (option 1) to do is to say that since fantasy doesn't match, then not only is helvetica (assuming it's actually available) the font that's actually used to render the text, but also since fantasy has no glyphs, Helvetica is also the first available font, and therefore its metrics are used to determine the line-height, ch unit, ex unit, etc. I support this.

"option 3" proposes one possible way to interpret the sentence that you propose to delete (about generic families always having to match), which would be to say that fantasy is in this case the first available font, and that the various measurments discussed above are based on it. That doesn't really say what they'd be, given that it's a conceptual font with no glyphs (and no obvious metrics) in it, but at least it wouldn't be based on helvetica. I think this is far fetched and undesirable, but if that sentence is there and means something I can't think of anything else than "option 2" or this "option 3".

Option 1 seems useful. Option 2 less so, but still sane. Option 3 seems just bad/silly to me. If anyone has a different understanding of what that sentence means, it'd be good to hear it before we remove it.

@litherum
Copy link
Contributor Author

Oh, I think I understand. You're proving that my statement:

The difference between fantasy mapping to a font that supports 0 characters, and fantasy not mapping to any font, is untestable.

is false.

I believe you are correct, and my statement is false. Even if fantasy supports 0 characters, its presence is still observable, because it still will have metrics and therefore affect line height. Cool.

@litherum
Copy link
Contributor Author

I'd like to propose option 1.

@tabatkins
Copy link
Member

Agree, option 1 seems best all around.

Looping back to @frivoal's earlier question:

If we do go with behavior 1, in order to set author's expectations it would be useful to specify whether:

  • the fallback must be independent of the specified font stack
  • the fallback may be influenced by the last font in the specified font stack if it is generic
  • the fallback may be influenced by the last generic font in the specified font stack, even if it is followed by non generics
  • the fallback may be influenced by [... some other specific thing ...]
  • the fallback may be influenced by the specified font stack in arbitrary ways up to the UA

Any opinions? @koji seems to be suggesting it's the last one (influenced in arbitrary UA-specific ways) in Chrome.

@litherum
Copy link
Contributor Author
litherum commented Oct 29, 2019

I assume that, in those questions, "fallback" means "the font that is used when the browser falls off the end of the font-family list".

In that case, I don't see any benefit to specifying how this font is picked. If the author wants the browser to pick a particular font, they should just name the font in the font-family list.

I do see benefit in leaving it unspecified because:

  • We use platform (Core Text) APIs to do it, and these APIs were not created with the web, or any web concepts, in mind
  • Browsers should be free to gather insight from any/all signals that the author has already provided in order to make the best pick possible.

(I believe I'm agreeing with @kojiishi)

@tabatkins
Copy link
Member

Cool, that's a useful answer. I think it would still be useful to give authors the advice that using a generic font-family can be used in that resolution, so they should use one, but other than that leaving it up to the UA sounds great to me.

@AmeliaBR
Copy link
Contributor
AmeliaBR commented Oct 29, 2019

Re Florian's suggested list of possible heuristics:

If the generic keywords match as regular fonts (and may not match all characters), that means that font-family: serif, monospace; is valid. So any answer to the question about how generics affect after-the-stack fallbacks needs to consider this case. I'd read that declaration as a sign that the author prefers a proportional serif font, so it should be the first generic in the list that should influence additional generics, not the last one.

It would also be nice if UAs other than Firefox offered a built-in way for multilingual users to select composite families for how the keywords apply to different scripts.

But that said: I'm OK leaving this vague and UA dependent. UAs should try to find a font to render each glyph in the text and they may use the information in the font stack to help select a harmonious font if there are multiple options available.

That's consistent with the current text for the font-matching algorithm, but extra notes for authors sound reasonable.

So there would be the following changes to the spec text:

(1) change the authoring guidance for font-family.

The current text is:

Authors are encouraged to append a generic font family as a last alternative for improved robustness.

New text would be something like:

Authors are encouraged to include a generic font family in the list, for improved robustness.

Note: A generic font family is not guaranteed to match every characters in every script.
However, generic keywords used in the font stack may affect additional fallback fonts selected by the user agent according to the [link]font-matching algorithm.
Alternatively, authors may choose to provide a web font for fallback for the generic font family.
This font would only be downloaded if the user agent's font for that generic family does not include the necessary characters for the text being rendered.

(2) Remove the requirement on having generic fonts match something.

Current text:

Each generic font family must always map to at least one matched font face. However, a single generic font family may be a composite face combining different typefaces…

User agents should provide reasonable default choices for the generic font families, that express the characteristics of each family as well as possible, within the limits allowed by the underlying technology. User agents are encouraged to allow users to select alternative faces for the generic font families.

Replacement (borrowing some of the text from the new "standard font families" section):

Generic font family keywords map to specific installed or system fonts based on their characteristics.
They may not all exist on every platform or operating system, and are not required to map to a concrete font face.
A single generic font family may be a composite face combining different typefaces…

Any default choices provided by a user agents for the generic font families should express the characteristics of each family as well as possible, within the limits allowed by the underlying technology. User agents are encouraged to allow users to select alternative faces for the generic font families.

(3) Remove the distinction between generics and the new "standard" families

That means including the new keywords within the definition of <generic-font-family> & probably collapsing those two sections.

@xfq xfq added the i18n-tracker Group bringing to attention of Internationalization, or tracked by i18n but not needing response. label Nov 1, 2019
@svgeesus
Copy link
Contributor
svgeesus commented Nov 7, 2019

I agree with option 1.

which would be to say that fantasy is in this case the first available font, and that the various measurments discussed above are based on it. That doesn't really say what they'd be, given that it's a conceptual font with no glyphs (and no obvious metrics) in it

A very good reason to not pick option 3.

My mental model is that the font stack consists of the following items, in order

  1. Whatever real font families have been specified
  2. Whatever generic family has been specified, if there is one
  3. Some sort of unspecified and implementation-specific fallback font, which may be composite, and is going for widest codepoint coverage. Details of this are not exposed in CSS (but the point about first available font and metrics makes me wonder
  4. Often, and unspecified and implementation-specific last-resort fallback. This may be a special font (like the one with the hex code as the glyph) or just a font with a missing-glyph.

Thus, I would not have expected any font(s0 specified after the first generic family to be used. I wouldn't have expected them to cause an error, just that they would not be used.

@svgeesus
Copy link
Contributor
svgeesus commented Nov 7, 2019

@Amelia, I like all your suggested wording changes.

@litherum
Copy link
Contributor Author

It sounds like there's general agreement on this. I'll Agenda+ it to try to get a resolution.

@frivoal
Copy link
Collaborator
frivoal commented Nov 14, 2019

Thus, I would not have expected any font(s) specified after the first generic family to be used. I wouldn't have expected them to cause an error, just that they would not be used.

I don't understand this. Unless generic font families are required to produce some glyph for every code point (in other words option 2, which you're not advocating for), then falling through a generic font family to whatever is after it, be it another generic, or a "real" font family, seems to be a logical necessity.

@svgeesus
Copy link
Contributor

Unless generic font families are required to produce some glyph for every code point (in other words option 2, which you're not advocating for),

correct

then falling through a generic font family to whatever is after it,

which is step 3 in my mental model, listed above. If the generic (step 2) fails to produce a glyph, you are onto steps 3 and then 4.

@fantasai
Copy link
Collaborator
fantasai commented Dec 3, 2019

@svgeesus Not sure I understand. What happens if the author specified font-family: serif, Helvetica instead of font-family: Helvetica, serif?

@svgeesus
Copy link
Contributor
svgeesus commented Dec 3, 2019

The difference is that @frivoal says

falling through a generic font family to whatever is after it, be it another generic, or a "real" font family

so Helvetica would be used

while I am thinking that if serif fails, we are on to step 3 listed above

so the implementation-specific, wide-coverage fallback font would be used.

@heycam
Copy link
Contributor
heycam commented Dec 4, 2019

Do we need to add wording about which generic, if multiple are listed, influence any implementation specific system fallback?

@jfkthame

@jfkthame
Copy link
Contributor
jfkthame commented Dec 4, 2019

Presumably the first generic mentioned should be the one to influence fallback after we fall off the end of the font-family list.

@jfkthame
Copy link
Contributor
jfkthame commented Dec 4, 2019

@svgeesus wrote:

My mental model is that the font stack consists of the following items, in order

  1. Whatever real font families have been specified

  2. Whatever generic family has been specified, if there is one

  3. Some sort of unspecified and implementation-specific fallback font, which may be composite, and is going for widest codepoint coverage. Details of this are not exposed in CSS (but the point about first available font and metrics makes me wonder

  4. Often, and unspecified and implementation-specific last-resort fallback. This may be a special font (like the one with the hex code as the glyph) or just a font with a missing-glyph.

Thus, I would not have expected any font(s0 specified after the first generic family to be used. I wouldn't have expected them to cause an error, just that they would not be used.

FWIW, I don't think I agree with this model. If the author specifies intermingled real font families and generic families in the font-family list, we try each of them in the order listed, regardless of which kind of family name they are.

So it's entirely legitimate (although rarely useful, I expect) to say something like

font-family: serif, "My Serif Font", sans-serif;

and the expectation is that we'll first try whatever font (or set of fonts) the UA provides for serif; but if a character is not available in that (those) font(s), we next try the specifically-named "My Serif Font" (perhaps it's a webfont that provides rare characters, but we don't want to download it at all if the serif generic has adequate coverage); and if that also fails, try the UA's sans-serif as well.

@svgeesus
Copy link
Contributor
svgeesus commented Dec 5, 2019

As I said, that was my mental model (ie my interpretation of the spec). I agree that the other interpretation is also plausible.

I'm fine with clarifying the spec in whichever way maximizes interop.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-fonts] Don't require browsers to always match every generic font family to a concrete font family, and agreed to the following:

  • RESOLVED: serif, sanserif, and monospace must match, all other generics should match if appropriate.
The full IRC log of that discussion <dael> Topic: [css-fonts] Don't require browsers to always match every generic font family to a concrete font family
<fantasai> Technically, the reference draft for patent review is the latest WD published within 90 days after FPWD, fwiw.
<dael> github: https://github.com//issues/4442#issuecomment-553707851
<dael> myles: Was doing edits for new system font families. I couldn't make them regular generic font families b/c they have to be mapped.
<dael> myles: Was thinking and reason spec says have to have mapping is it's supposed to help authors where they can says font-family: fantasy and you get something in every browser
<dael> myles: THat's cool except there's 2 problems. 1 for any new font-family old browsers won't have mapping. 2 is there's no guar. that font supports your characters. So author can't set and forget because if use an unsupported character where it doesn't look right anyway
<dael> myles: That there's this statement I don't think it helps anyone and makes spec more complicated where some are generic and some are standard and I wish I could join them
<dael> fantasai: One distinction is a system might not have sanserif that's UI and wanted to be okay that this doesn't exist. But any sanserif on the system should have a mapping for sanserif. I don't want ot lose that
<dael> myles: I could move the must sentince into specific generic font-families. sanserif family must have mapping
<dael> chris: can we do it for the 3 real ones and not require fantasy and cursive?
<dael> myles: Don't see why not
<dael> heycam: Mapping but not requirement on character coverage?
<dael> myles: Correct. THat's current state
<dael> florian: In discussion chris and I had different understanding. When you write make it clear which version is right.
<dael> chris: Agree and I think I'm wrong and we should make it clear
<dael> myles: Yeah and I'll make examples
<dael> florian: I used to interpret like chris and I don't think it's right
<dael> chris: And mine doesn't have benefit it's mapping from CSS1
<dael> AmeliaBR: Important is to update author guidance ot match reality. Some UAs generic fonts won't have full coverage and will fall back to next in stack.
<dael> myles: Anyone from FF that says it's true?
<dael> chris: Jonathan Q was on the thread
<chris> s/Q/Kew/
<astearns> s/Q/Kew/
<dael> AmeliaBR: They do composit but allow authors to change mappings for languages so not sure how it falls back
<dael> fantasai: And you can just change it
<fantasai> s/authors/users/
<fantasai> s/fantasai: And you can just change it//
<dael> myles: Prop: Move the normative sentince about font-families mapping to a font into the serif, sanserif, and monospace items.
<dael> florian: And add a note that the font might not cover everything
<dael> florian: I support this
<AmeliaBR> https://github.com//issues/4442#issuecomment-547627749
<dael> astearns: Concerns?
<dael> astearns: fantasai thinks cursive should be in the list
<dael> fantasai: If there's not one on the system it's okay not to map
<dael> AmeliaBR: Cursive is such a mess you get different results in different browsers
<dael> myles: I think if we jsut say all these should map to something if such a font exists covers it
<fantasai> +1 to Amelia's definition
<dael> AmeliaBR: I think that's fair for entire list include system-ui. If a font exists that matches definitions UA should map to the keyword. If you don't have a sensible mapping don'ts do oone
<dael> astearns: serif, sanserif, and monospace must match, all others should match if appropriate
<dael> chris: myles you'll edit?
<dael> myles: Yeah
<dael> heycam: Must match and not distinction; does that imfluence first matching?
<dael> myles: They interact. You found the corner case where it is observable
<dael> AmeliaBR: Also effects cases where this is a match but no character
<dael> astearns: Then you get line height with the font
<dael> florian: I think the concern I have which can be separate is that though not unique to generic fonts if you say use serif to mean [missed] and then manually provide one in the fallback you get the layout but with the wrong font metrics.
<dael> florian: That's not nice
<dael> myles: It's a separate topic
<dael> florian: Agree but we were getting there
<dael> AmeliaBR: It's worth a second issue specfically on font metrics
<astearns> s/[missed]/Mincho/
<dael> florian: Will open one
<dael> chris: There are issues on similar things
<dael> florian: I'll look at existing and make a new if it's not there
<dael> astearns: Obj to serif, sanserif, and monospace must match, all other generics should match if appropriate
<dael> AmeliaBR: Earlier in chat I linked to my comment in issue that breaks down other places in spec with coordinating edits. I think those are editorial, though.
<dael> RESOLVED: serif, sanserif, and monospace must match, all other generics should match if appropriate.
<dael> astearns: AmeliaBR it would be great if you can review once myles does edits
<dael> astearns: Should we discussed first available height issue?
<dael> florian: I'll make github first
<chris> s/similar things/similar things, like nastaliq and fangsong
<dael> heycam: Also which generic in the list determines fallback at the end. Should I make it a separate issue? It's if there should be wording to say which influences.
<dael> AmeliaBR: Tendency was leave to UA discression but if you want normative we want a separate discussion
<dael> astearns: Let's make that a separate issue

@svgeesus
Copy link
Contributor

Removing the needs edits as they have been made ages ago

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-fonts-4 Current Work i18n-tracker Group bringing to attention of Internationalization, or tracked by i18n but not needing response.
Projects
None yet
Development

No branches or pull requests