Chromium 83 での macOS system-ui フォントの可変フォント オプションの追加

Catalina では、macOS に新しい統合可変システム フォントが導入されます。

CSS Fonts Module Level 4 仕様の 「system-ui」セクションでは、system-ui フォント キーワードが定義されています。これにより、デベロッパーは、サイトやアプリで、組み込みの、ターボ最適化された、ローカライズされた、超高品質の、ダウンロード不要の、デフォルトのオペレーティング システム フォントを直接使用できます。

body {
  font-family: system-ui;
}

このタイポグラフィの選択は、「このユーザーの現在のロケールのデフォルトのシステム フォントを使用する」と言うのと同等です。

macOS では、system-ui フォントは San Francisco です。これは、デザインチームが精査、テストを行い、最近アップグレードしたフォントです。まず、Catalina の新しいエキサイティングなバリアブル フォント機能について説明し、次に、いくつかのバグと Chromium エンジニアがそれらを解決した方法について説明します。

この記事は、可変フォントについてすでに理解していることを前提としています。そうでない場合は、ウェブ上の可変フォント入門と以下の動画をご覧ください。

ブラウザの互換性

この記事の執筆時点では、system-ui は Chromium(56 以降)、Edge(79 以降)、Safari(11 以降)、Firefox(43 以降、ただし -apple-system キーワードを使用)でサポートされています。最新情報については、可変フォントを使用できますか?をご覧ください。

新しい力

Catalina でシステム フォントに導入された新機能が、Chromium 83 以降でウェブ デベロッパーに提供されるようになりました。system-ui フォントにより多くの変数設定が追加されました。光学サイズと 2 つの独自のウェイト調整です。

Mojave
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750
  ;
}
Catalina
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750,
    'opsz' 20,
    'GRAD' 400,
    'YAXS' 400
  ;
}

Mojave では、system-uiwght 設定のみの可変フォントです。Catalina の system-ui は、wghtopszGRADYAXS の設定がある可変フォントです。

プログレッシブ エンハンスメントの設計機会がいくつかあるようです。必要に応じて、システム フォントの微妙な違いを詳しく調べてください。

wght

0900 の範囲のフォントの太さを指定します。すべての文字に同じ太さが適用されます。

/* 0-900 */
font-variation-settings: 'wght' 750;

opsz

光学サイジングはカーニングや文字間隔に似ていますが、間隔は数学ではなく人間の目で調整されます。19 以下の値はテキストと本文のコピーの間隔を調整するためのもので、20 以上の値はディスプレイ ヘッダーとタイトルの間隔を調整するためのものです。

/* 19 or 20 */
font-variation-settings: 'opsz' 20;

GRAD

ウェイトと似ていますが、水平方向のスペースには影響しません。4001000 の値を受け付けます。

/* 400-1000 */
font-variation-settings: 'GRAD' 500;

YAXS

グリフを縦方向に拡大します。4001000 の値を受け付けます。

/* 400-1000 */
font-variation-settings: 'YAXS' 500;

オプションの組み合わせ

数行の CSS を使用して、フォント設定を任意の太字に変更したり、他の興味深い組み合わせを試したりできます。

font-weight: 700;
font-weight: bold;
font-variation-settings: 'wght' 750, 'YAXS' 600, 'GRAD' 500, 'opsz' 20;

これで、macOS の Chromium ユーザーには、アップグレードされたカスタムの 750 ウェイトが他の楽しい調整とともに表示されます 👍

macOS 10.15 では、システム フォントに新機能が追加されました。また、macOS 10.15 では、Chromium バグトラッカーに system-ui という厄介なバグが記録されました。関係があるのかな!?

付録: system-ui 回帰

このストーリーは別のバグ(#1005969)から始まります。これは、system-ui フォントのスペーシングが狭く、詰まっているように見えるため、macOS 10.15 に対して報告されました。

Facebook グループ ページの 2 つの段落の比較。左が Chrome、右が Safari。Chrome の方がわずかに間隔が狭い
左が Chrome(トラッキングが厳密)、右が Safari(光学的な間隔が良好)

背景

macOS 10.14 で、段落や見出しのフォントサイズを大きくしたり小さくしたりすると、フォントが別のものに「スナップ」されることに気づいたことはありませんか?

Mojave(macOS 10.14)では、system-ui フォントはターゲットのフォントサイズに応じて 2 つのフォントを切り替えていました。テキストが 20px の場合、macOS は「San Francisco Text」を使用していました。テキストが 20px 以上の場合は、macOS で「San Francisco Display」が使用されていました。光学サイズは、2 つの別々のフォントに静的に組み込まれていました。

Catalina(macOS 10.15)では、San Francisco の新しい統合可変フォントがリリースされました。「テキスト」と「ディスプレイ」の管理は不要になります。また、前述の新しいバリエーション設定 opsz も追加されました。

h1 {
  font-variation-settings: 'opsz' 20;
}

残念ながら、新しい Catalina フォントのデフォルトの opsz 値は 20 であり、Chromium エンジニアは opsz をシステム フォントに適用する準備ができていませんでした。これにより、小さいサイズが狭く表示されていました。

この問題を解決するため、Chromium はシステム フォントに opsz を正しく適用する必要がありました。これにより、問題 #1005969 が修正されました。勝利!それとも…?

未完了

ここで問題が発生しました。Chromium は opsz を適用しましたが、まだ正しく表示されません。Mac のシステム フォントには、水平方向のスペーシングを調整する trak という追加のフォント テーブルがあります。修正に取り組んでいる間、Chromium のエンジニアは、macOS で CTFontRef オブジェクトから水平方向の指標を取得する際に、trak 指標がすでに指標の結果に反映されていることに気づきました。Chromium のシェーピング ライブラリ HarfBuzz には、trak 値がまだ考慮されていない指標が必要です。

system-ui とそのすべてのフォントの太さとバリエーションがリストに表示されています。そのうちの半分には重み付けの違いが適用されていません。
左: フォントサイズ 19 以下に太字の太さが適用されています。右: フォントサイズが 20 以上の場合は太字のスタイルが失われる

内部的には、Skia(同じ名前の書体ではなくグラフィック ライブラリ)は、CoreGraphicsCGFontRef クラスと CoreTextCTFontRef クラスの両方を使用します。これらのオブジェクト間の内部変換(下位互換性を維持し、両方のクラスで必要な API にアクセスするために使用)が必要なため、特定の状況で Skia の太さ情報が失われ、太字フォントが機能しなくなります。この問題は Issue #1057654 で追跡されていました。

Chromium が macOS 10.11 をサポートしているため、Skia は引き続き macOS 10.11 をサポートする必要があります。10.11 では、「San Francisco Text」と「San Francisco Display」のフォントは可変フォントではありませんでした。むしろ、利用可能なウェイトごとに個別のフォントのファミリーでした。ある時点で、グリフ ID が互いに同期しなくなりました。そのため、Skia が「San Francisco Text」でテキスト整形(描画可能なグリフへのテキストの変換)を行った場合、「San Francisco Display」で描画すると意味不明な文字になります。逆の場合も同様です。Skia が別のサイズを要求した場合でも、macOS が別のサイズに切り替える可能性があります。常にフォントの 1 つを使用して、それをスケーリングする(より大きなサイズを要求するのではなく、マトリックスを使用して拡大する)ことは可能ですが、CoreText には、sbix(カラー絵文字)グリフを拡大しない(縮小のみ)という問題があります。実際はもう少し複雑です。CoreText は、実際にはマトリックスの適用後に垂直方向の範囲を制限しているようです。これは、45 度の角度で絵文字を描画できないことに関連しているようです。いずれにしても、絵文字を大きく表示したい場合は、フォントのコピーを作成して大きなバージョンを取得する必要があります。

そこで、同じ基盤となるフォントデータが使用されるようにしながら、内部でさまざまなサイズの CTFont オブジェクトのコピーを作成するために、Chromium は CTFont から CGFont を取り出し、CGFont から新しい CTFont を作成しました(CGFont オブジェクトはサイズに依存しません。魔法のような切り替えは CoreText レベルで行われます)。10.154 までは問題なく動作していました。10.15 では、このラウンド トリップで情報が失われすぎ、重み付けの問題が発生しました。Flutter は重みに関する問題に気づき、サイズ変更の代替修正が行われました。これにより、CoreText の古いながらもドキュメント化されていない属性を使用して光学サイズを直接制御しながら、元の CTFont から新しい CTFont を直接作成できるようになりました。これにより、10.11 での動作が維持され、他の問題(光学サイズをデフォルト値に明示的に設定するなど)も修正されます。

ただし、これにより、フォントの CoreText の「魔法」がより多く保持されます。その 1 つは、trak テーブル(Chromium は別のドキュメント化されていない属性を使用してその適用をすでに抑制しようとしていた)だけでなく、何らかの方法でグリフの進みを調整しているように見えることです。

CGFont はこのような「魔法」を一切行わないため、Chromium は CTFont から CGFont を取得して、それを進捗の取得にのみ使用できるかもしれません。残念ながら、CoreText は他の方法でもフォントを操作することが知られているため、この方法は機能しません。たとえば、リクエストしたサイズよりも少し大きく絵文字を表示します(サイズを少し大きくします)。CGFont はこのことを認識していないため、あるサイズで測定しても CoreText がそれより少し大きく描画するため、sbix ベースの絵文字が互いに近くなりすぎます。Chromium は CTFont の進歩を望んでいますが、トラッキングなしで、できれば他の混乱なしでそれを望んでいます。

スペーシングの問題の修正には、相互に関連する Blink と Skia の修正が必要だったため、Chromium エンジニアは「単に元に戻す」ことで問題を解決できませんでした。Chromium のエンジニアは、Skia のフォント関連のコードパスを変更するために別のビルドフラグを使用することも試しましたが、太字フォントの問題は解決したものの、スペーシングの問題が再発しました。

解決策

最終的に、Chromium は両方の問題を修正したいと考えました。Chromium は、システム フォントのフォント テーブルのバイナリデータから水平方向の指標を直接取得するために、HarfBuzz の組み込みフォント OpenType フォント指標関数を使用するようになりました。これにより、フォントに trak テーブルがある場合、Chromium は CoreText と Skia を回避します(絵文字フォントの場合を除く)。

system-ui とそのすべてのフォントの太さとバリエーションをリストで表示。以前は機能していなかった半分が、現在は正常に表示されています。

それまでの間、Skia Issue #10123 で、Skia での完全な修正を追跡し、HarfBuzz を介した現在の修正ではなく、Skia を使用してシステム フォントの指標を取得する処理に戻します。