unjs / fontaine

Automatic font fallback based on font metrics

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

enable `size-adjust` metric calculation

danielroe opened this issue · comments

Currently we can use metrics to adjust vertical height accurately. There's still a horizontal mismatch though, even if slight, and we can likely solve this by applying the right metrics to size-adjust.

I think you can improve the horizontal mismatch, but not solve it.

Looking at the "On Font Width..." section at the bottom of this notes on calculating font metric overrides document, because the width of each character contributes a different amount to the width of the line, the size-adjust width adjustment can only be calculated accurately if you know the specific set of characters it will apply to.

In this example, you can see how size-adjust can make the fallback font match up exactly for the configured text value, "abcdefghijklmnopqrstuvwxyz":
image

But for different text content, that size adjustment will no longer match so perfectly:
image

That is correct. As the document says:

Quantifying width has many potential variations: for example, weighting by character frequency, weighing some characters more heavily (e.g. narrow/wide characters like “i,j,m,w”), taking the average width of all glyphs (i.e. not just “abc...z”), etc. Some of these “fancier” approaches might not generalize well across languages.

Nevertheless, it offers a real improvement 😉

As far as I understand Next 13 just implemented this too 😄 https://twitter.com/Una/status/1584967596847542272
Wish it was not coupled to Next and a separate project though

This is fundamentally an awesome idea. My bet is that in the long run, what fontaine and Next are doing becomes native browser functionality in some way

FYI - For anyone who cares about the CLS core web vital on mobile, size-adjust does not work on Chrome for Android. A bug for it is filed in the link below.
https://bugs.chromium.org/p/chromium/issues/detail?id=1370818

I use Malte Ubl's tool here to get my size-adjust calculations: https://www.industrialempathy.com/perfect-ish-font-fallback/. Source code here: https://www.industrialempathy.com/perfect-ish-font-fallback/font.js (NOTE: not open source, likely copyrighted).

I admittedly don't follow the logic for resizeText, but it works wonderfully. I wonder if there's a way to use the existing font metrics from capsize to compute something similar. Example: Fira Sans with a fallback of Arial generates this code:

/* Make a custom fallback font based on the local Arial */
@font-face {
    font-family: "Fira Sans-fallback";
    size-adjust: 102.59%;
    src: local("Arial");
}

Metrics:

"arial": {
    "familyName": "Arial",
    "category": "sans-serif",
    "capHeight": 1467,
    "ascent": 1854,
    "descent": -434,
    "lineGap": 67,
    "unitsPerEm": 2048,
    "xHeight": 1062,
    "xWidthAvg": 904
  },
"firaSans": {
    "familyName": "Fira Sans",
    "category": "sans-serif",
    "capHeight": 689,
    "ascent": 935,
    "descent": -265,
    "lineGap": 0,
    "unitsPerEm": 1000,
    "xHeight": 527,
    "xWidthAvg": 458
  },

MDN says:

The size-adjust descriptor behaves in a similar fashion to the font-size-adjust property. It calculates an adjustment per font by matching ex heights.

But it's unclear what "matching ex heights" means in terms of the computations.

BTW, @danielroe, I started using size-adjust recently on Chrome for Android and it now works. BTW, Android does not have many common web fonts, so the comparison from one custom font to a fallback font will only work if the fallback font is Roboto or Noto Serif

http://fontfamily.io/

implemented in #181!