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

Catalina は、新しい統合可変システム フォントを macOS に導入しました。

Dominik Röttsches 氏
Dominik Röttsches

CSS Fonts モジュール レベル 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 番太の太さが、その他に面白い微調整を加えた形で表示されます 👍?

遊び場

下の Glitch の [Remix to Edit] をクリックして Glitch の編集可能なコピーを入手し、新しい font-variation-settings オプションを編集してフォントにどのように影響するかを確認します。この Glitch は macOS Catalina デバイスを使用している場合にのみ動作します。

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

付録: system-ui 回帰

このストーリーは、別のバグ(#1005969)から始まります。この問題は macOS 10.15 で報告されています。system-ui のフォントの間隔が狭く詰め込まれているためです。

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)は、サンフランシスコ向けの新しい統一可変フォントを出荷しました。[テキスト] と [ディスプレイ] を管理する必要がなくなります。また、前述の新しいバリエーション設定 opsz も追加されました。

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

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

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

未完了

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

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

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

Chromium が現在もサポートしているため、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 が重みの問題を検出しました。サイズ変更のための代替修正として、元の CTFont から直接新しい CTFont を作成し、CoreText にドキュメント化されていない古い属性を使用して光学サイズを直接制御しました。これにより、10.11 での動作が維持され、その他の問題(光学サイズをデフォルト値に明示的に設定するなど)が修正されます。

ただし、この方法ではフォント内の CoreText の「マジック」をより有効に活用することができます。そのうちの一つは、trak テーブル(Chromium がすでにドキュメント化されていない属性を通じて抑制しようとしていたアプリケーション)以外のなんらかの方法で、グリフの進行を微調整していることのようです。

CGFont はそのような「魔法」のいずれも行わないので、Chromium は CTFont から CGFont を取り除いて、それを使用して機能を強化できる可能性があります。残念ながら、CoreText は他の方法でもフォントによって劣化することが報告されているため、この方法はうまくいきません。たとえば、小さな絵文字は、実際にリクエストしたよりも少し大きくなります(サイズを少し大きくします)。CGFont はこれを認識していないため、スビックスベースの絵文字が互いに近すぎることになります。これは、1 つのサイズで測定しますが、CoreText を使用すると、いくらか大きくなります。Chromium は CTFont の進化を望んでいますが、トラッキングなしで、できれば他の面倒な機能がないことを望んでいます。

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

解決方法

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

system-ui と、そのすべてのフォントの太さ、バリエーションのリストの表示。以前は機能していなかった半分が、今はうまくいったように見えます。

それまでの間、Skia Issue #10123 が引き続きあり、Skia でのこの問題を完全に追跡し、HarfBuzz で行われる現在の修正ではなく、Skia を使用してそこからシステム フォント指標を取得します。