Skip to content

Update font-family support #213

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Update font-family support #213

wants to merge 3 commits into from

Conversation

asamuzaK
Copy link
Contributor

@asamuzaK asamuzaK commented Jun 8, 2025

Fix #212

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

Thanks for your quick work here! However now I am wondering if the spec or tests also need updates...

https://wpt.fyi/results/css/cssom/font-family-serialization-001.html?label=experimental&label=master&aligned is interesting in particular.

});

// see https://drafts.csswg.org/css-fonts-4/#changes-2021-12-21
it("support generic keywords that have been removed from the spec", () => {
Copy link
Member

Choose a reason for hiding this comment

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

Probably we should not support them? I guess the test needs updates?

}
});

it("should support `-webkit-` prefixed family name", () => {
Copy link
Member

Choose a reason for hiding this comment

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

Is this in any spec? If not, maybe we should open a spec issue and/or fix the test?

@asamuzaK
Copy link
Contributor Author

asamuzaK commented Jun 9, 2025

Re: https://wpt.fyi/results/css/cssom/font-family-serialization-001.html
I don't think this is a good test, but I don't have any suggestions for a fix.
And I don't know about the history of spec changes, but the file on which the tests are based appears to have been last updated four years ago.
See https://github.com/web-platform-tests/wpt/blob/master/css/css-fonts/support/font-family-keywords.js

Some thoughts from the test results:

  • Chrome:
    • If the family name is within the ASCII range, strip quotes, e.g. "emoji" -> emoji.
    • If the family name within quotes are the one of keywords, then don't remove quotes, e.g. "serif" -> "serif".
      It treats serif and "serif" as different family name.
  • Firefox:
    • Leave the quoted family name as is, e.g. "serif" -> "serif", "emoji" -> "emoji".
  • Safari:
    • If the family name is within the ASCII range, strip quotes, e.g. "emoji" -> emoji.
    • If the family name within quotes are the one of <generic-family> keywords, strip quotes in this case too, e.g. "serif" -> serif.
    • If the family name with -webkit- has standard, replace with the standard one, e.g.-webkit-serif -> serif.
    • For other family name with -webkit-, replace it based on the internal mapping, e.g. -webkit-body -> Times.

It's just my guess, but from the above results, I don't think any browsers have implemented emoji or fangsong as <generic-family> keywords.
They are simply treated as non generic family names.

Also note that emoji and fangsong without quotes are both valid family names, even if they are not in <generic-family>,
so all browsers are passing first Serialization of <generic-family> test.
But our implementation expects unquoted family name to start with upper case, so we failed emoji to pass.
See https://github.com/jsdom/cssstyle/blob/main/lib/properties/fontFamily.js#L28
We can remove this part, but it would make verification more difficult.

@domenic
Copy link
Member

domenic commented Jun 9, 2025

Thanks for the investigation! Upon reading the spec in more detail, I think the test should update https://github.com/web-platform-tests/wpt/blob/master/css/css-fonts/support/font-family-keywords.js to match the list in https://drafts.csswg.org/css-fonts-4/#generic-font-families . I will send a PR for that. (web-platform-tests/wpt#53015)

Analysis of the tests:

  • Serialization of <generic-family>: the expectations match the spec. You parse as <generic-family> and that gets serialized back as a keyword.
  • Serialization of quoted "<generic-family>": the expectations match the spec. You parse as <family-name>'s <string> branch, which serializes with quotes, and is separate from <generic-family>. See https://drafts.csswg.org/css-fonts-4/#ex-valid-unusual-generic-like .
  • Serialization of prefixed -webkit-<generic-family>: the expectations match the spec. You parse as <family-name>'s <custom-ident>+ branch, which is kept as an identifier (since there are no spaces), and serialized back that way.
  • Serialization of ${kNonGenericFontFamilyKeywords}: same as -webkit prefixes, these are all single <custom-ident>s.

For our implementation in cssstyle, I think the minimal change is to just update the keyword list to match https://drafts.csswg.org/css-fonts-4/#generic-font-families . (Maybe omit generic(*) if they are too complicated.) We should not include special casing for -webkit.

Eventually, we could write completely spec-compliant parsing and serializing code for font-families. This would involve removing the current uppercase assumption and instead using a parser that can recognize:

  • keywords (for <generic-family>)
  • strings (for one part of <family-name>)
  • custom-idents (for the other part of <family-name>)

But this is probably much harder.

@asamuzaK
Copy link
Contributor Author

asamuzaK commented Jun 9, 2025

Just to confirm, you will get a result like this:

style.font = "medium foo"; // no generic font family

console.log(style.fontFamily); // `foo`

It should be okay then?

@asamuzaK
Copy link
Contributor Author

asamuzaK commented Jun 9, 2025

Updated the implementation, but omitted generic().
We need to implement a new parser to handle CSS functions like generic(), repeat() (see #146), and so on.

@asamuzaK asamuzaK force-pushed the font branch 2 times, most recently from 978cf65 to d274842 Compare June 9, 2025 23:42
@asamuzaK asamuzaK marked this pull request as draft June 10, 2025 00:07
@domenic
Copy link
Member

domenic commented Jun 10, 2025

Just to confirm, you will get a result like this:

style.font = "medium foo"; // no generic font family

console.log(style.fontFamily); // `foo`

It should be okay then?

This appears to be how browsers behave, so yeah, that seems good!

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.

Regression with font family serialization
2 participants