w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.43k stars 652 forks source link

[css-fonts-4] Clarify how the computed font-size is determined for size keyword #3906

Open fred-wang opened 5 years ago

fred-wang commented 5 years ago

cc @emilio @rwlbuis @bkardell @bfgeek

Spec: https://drafts.csswg.org/css-fonts-4/#font-size-prop

For example Emilio gave me this example:

  <div style="font-family: serif">Serif <div style="font-family: monospace">mono</div></div>

The first div has size 16px and the second 13px in all browsers. font-size on them is the default "medium" value. Compare with:

  <div style="font-size: 16px"><div style="font-family: serif">Serif <div style="font-family: monospace">mono</div></div></div>

Currently, the spec suggests some scale factors but maybe it should make clear that the computed font-size is determined from the computed font-family, lang, user preferences etc

fred-wang commented 5 years ago

(Note: This is blocking #3746 ; we need to decide how the computed font-size is calculated if in addition one of these inner divs have a script level change.)

litherum commented 5 years ago

WebKit has:

defaultFontSize:
  type: int
  initial: 16
  onChange: setNeedsRecalcStyleInAllFrames
defaultFixedFontSize:
  type: int
  initial: 13
  onChange: setNeedsRecalcStyleInAllFrames

and also:

bool useFixedDefaultSize() const { return familyCount() == 1 && firstFamily() == monospaceFamily; }

The rest of the relevant code is here.

The WebKit logic is therefore "if font-family has one item and its name is monospace then its font size get sets according to this table:"

CSS size keyword Font size
xx-small 9
x-small 10
small 12
medium 13
large 16
x-large 20
xx-large 26
-webkit-xxx-large 39

Else, its font size get sets according to this table:

CSS size keyword Font size
xx-small 9
x-small 10
small 13
medium 16
large 18
x-large 24
xx-large 32
-webkit-xxx-large 48
emilio commented 5 years ago

In Gecko it's a bit more complex than that and it also depends on the language group.

The default values for those user settings are here, but you can really configure it as you want.

So in Gecko this for example will still render the mono text with 16px font-size for zh-HK by default: data:text/html, <div style="font-family: serif">Serif <div lang="zh-HK" style="font-size: monospace">mono</div></div>.

Other than that the logic is similar to WebKit. If there's a single generic font-family, then we get the base font-size for that generic, otherwise we use the variable font-size (which is 16px by default). Then with that base size we apply a similar mapping to WebKit:

https://searchfox.org/mozilla-central/rev/b9da45f63cb567244933c77b2c7e827a057d3f9b/servo/components/style/values/specified/font.rs#728

/cc @jfkthame

AmeliaBR commented 5 years ago

Most browsers have special legacy font-size rules for font-family: monospace that disappear with any other font-family declaration (even if the used font-family is the same), so it's worth separating out the main discussion from those quirks.

But that said, the presence of those quirks mean that font-size: normal doesn't have an absolute translation to px values throughout the page.

dbaron commented 5 years ago

Gecko used to have relatively complicated code to handle the case where a descendant inherited a font size or used a %, em, etc., font size while being different from its ancestor in terms of monospace or not, which would try to redo the font size computation from the nearest absolute ancestor as monospace or not. I think much of that code is gone (cc @Manishearth) but I don't remember for sure.

I'd also note that a number of years ago I had a proposal for replacing these separate font size preferences for monospace and non-monospace with a new value of font-size-adjust.

Gecko's defaults appear to be (at a quick skim, hopefully I didn't miss anything):

script (of tagged language or language detected from encoding) variable size monospace size
western, cyrillic, ar, el, he, "unicode" (undetected) 16 13 on mac/win, 12 on linux/android
ja, ko, zh-CN, zh-HK, zh-TW 16 16
th, devanagari, tamil, armn, beng, cans, ethi, geor, gujr, guru, khmr, mlym, orya, telu, knda, sinh, tibt, math 16 13
Manishearth commented 5 years ago

This is basically a dupe of https://github.com/w3c/csswg-drafts/issues/1835 . Given that Edge uses Blink now I think we should revisit this.

Note that Chrome supports language-dependent font sizes too, the functionality is just not exposed by default.

I think much of that code is gone (cc @Manishearth) but I don't remember for sure.

The code is much simpler now (it doesn't recascade), but it has the same effects. Basically, if a font-size is computed from a keyword value, including things like "50% of medium", or "2em on large" (or calc values), we store the origin of it as a keyword + calc. If the lang or family changes, we recompute the keyword for the new lang/family values and then apply the calc to get the new font size.

(The old code would walk up the tree and redo the cascade, which was complicated. Now we cascade additional state and the cascade code for font-size is slightly more complex. There may be slight behavioral differences when it comes to some edge cases with MathML scriptminsize but you really have to try)

svgeesus commented 5 years ago

Tests now on WPT

fred-wang commented 5 years ago

Tests now on WPT

Note that these are tests related to #3746 ; probably some dedicated font-size/font-family tests independent from math-script-level should be written too.

svgeesus commented 5 years ago

Note that these are tests related to #3746 ; probably some dedicated font-size/font-family tests independent from math-script-level should be written too.

Yes they should, but I wanted those approved so people can look at them during the discussion.

svgeesus commented 5 years ago

A quick CodePen showing results for Japanese, Traditional Chinese, and unspecified language

In Safari and Firefox, Japanese and Chinese monospaced both end up 16px . In Chrome, Chinese does but Japanese does not.

emilio commented 5 years ago

I was wrong about Firefox's behavior and we don't get the "first generic family", but only if it's just one: https://searchfox.org/mozilla-central/rev/9eb2f739c165b4e294929f7b99fbb4d90f8a396b/servo/components/style/values/computed/font.rs#537

So it's sort-of compatible with WebKit.

css-meeting-bot commented 5 years ago

The CSS Working Group just discussed Clarify how computed font-size is determined for size keyword, and agreed to the following:

The full IRC log of that discussion <TabAtkins> Topic: Clarify how computed font-size is determined for size keyword
<astearns> github: https://github.com/w3c/csswg-drafts/issues/3906
<fantasai> ACTION myles Add a note about the font-size: 0px vs min font-size web-compat issue
<trackbot> Created ACTION-879 - Add a note about the font-size: 0px vs min font-size web-compat issue [on Myles Maxfield - due 2019-06-11].
<TabAtkins> myles: I don't think we can get rid of the fact that monospace is special, for webcompat
<TabAtkins> chris: So this is really about the fact that Courier looks too big.
<TabAtkins> chris: And browsers also noticed that CJK fonts can look too big at 16px by default
<TabAtkins> emilio: in gecko we do this based on the generic family specified.
<TabAtkins> myles: So "a, b, serif" gets a different font size than "a, b, monospace"
<TabAtkins> dbaron: Yes, because of the assumption that those fonts are probably monospace as well
<TabAtkins> fremy: As I recall that's not what was implemented by browsers...
<TabAtkins> myles: In WK, we only adjust if you say *only* "monospace"
<TabAtkins> myles: So using font-family to dictate font-size is fundamnetally broken, we all agree
<TabAtkins> [we all agree]
<TabAtkins> myles: So the question is if we shoudl write down exactly how it's broken. it sounds like everyone does it differently
<TabAtkins> dbaron: Given there's incompatibility, there's maybe room to improve this
<fantasai> [emilio describes some details of how this works]
<TabAtkins> dbaron: AT one point I had part of a plan to replace with with font-size-adjust
<TabAtkins> dbaron: Probably not web-compatible, but maybe... Would require new values.
<TabAtkins> fremy: Last I recall Edge didn't do any adjustments, but at some point we got a bug and added new UA rules that only targeted elements that get monospace by default. We don't apply it to the *monospace value* tho.
<fantasai> TabAtkins: We should capture in the property that extra bit of information captured about whether size was specified as a size
<fantasai> TabAtkins: because browsers seem to do something special in that case
<fantasai> AmeliaBR: Keywords are a bit vague anyway
<fantasai> TabAtkins: No flexibility in that they convert to a <length>
<fantasai> TabAtkins: You honor a <length> as a <length>
<fantasai> TabAtkins: But that's not how browsers work
<fantasai> TabAtkins: We might need to keep it underdefined, but at least that there's some thing special going on
<fantasai> fremy: We have interop, so let's spec that
<fantasai> TabAtkins: OK, but let's capture there's something
<fantasai> emilio: Gecko code... when you have multiple families, we behave like WebKit
<fantasai> emilio: Yay interop!
<fantasai> AmeliaBR: so weird behavior, but cross-browser consistent
<fantasai> chris: So how are we resolving?
<TabAtkins> dbaron: The thing this was solving is really a use-case for font-size-adjust
<fantasai> dbaron: Like to say that the thing this was soliving is a use case for font-size-adjust
<TabAtkins> dbaron: I'd like to encourage the negine that doesn't ipmlement f-s-a to do that.
<fantasai> dbaron: Would like engine that doesn't implement font-size-adjust that doesn't implement it to fix it
<fantasai> dbaron: It's ugly because it's designed to be compatible with its non-existence
<fantasai> dbaron: It's a way of saying "i want to specify font-size in terms of x-height instead of font-size"
<chris> https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust#Browser_compatibility
<TabAtkins> astearns: So it sound slike proposal is to acknowledge reality in font-size property that it makes font-sizes strange.
<TabAtkins> astearns: And at minimum capture "it's strange" in the spec.
<dbaron> oh, actually, font-size-adjust may be behind the experimental web platform features flag in Chrome...
<fantasai> TabAtkins: Let's capture that keywords come with extra bit of info
<fantasai> TabAtkins: And also investigate if there's compat, andif so spec that
<fantasai> myles_: sgtm
<TabAtkins> astearns: Is there someone volunteering to do the investigation?
<TabAtkins> fremy: I volunteer.
<TabAtkins> astearns: proposal: acknowledge reality that font-size keywords have some weirdness with particular generic font families.
<TabAtkins> RESOLVED: Capture that font-size keywords carry an additional bit of information having some (unspecified) interaction with some font families.
<TabAtkins> astearns: Second is to deputize françois to try and capture what the weirdness is
<TabAtkins> RESOLVED: François does compat research on the effect of font-size keywords and generic font-families, and report back on interop.
FremyCompany commented 5 years ago

(To help myself in my volunteering effort of providing an updated description of the Webkit/Gecko behavior, here is the last time I talked about this: https://github.com/w3c/csswg-drafts/issues/1835#issuecomment-362025870)

svgeesus commented 5 months ago

@FremyCompany I assigned you because that June 2019 CSSWG resolution assigned you :)

Also changing the title to CSS Fonts 4