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

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

CSS フォント モジュール レベル 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 のカスタム ウェイトに他の微調整を加えたものが表示されます fitbit

遊び場

下の Glitch で [Remix to Edit] をクリックして Glitch の編集可能なコピーを入手し、新しい font-variation-settings オプションを編集してフォントへの影響を確認します。このグリッチは、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)では、San Francisco 用の新しい統合可変フォントがリリースされました。「テキスト」と「表示」の管理が不要になります。また、前述の新しいバリエーション設定 opsz も追加されました。

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

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

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

まだ完了していません

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

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

内部では、Skia(同名のタイポフェイスではなくグラフィック ライブラリ)は、CoreGraphicsCGFontRef クラスと CoreTextCTFontRef クラスの両方を使用します。これらのオブジェクト間の内部変換(下位互換性を維持し、両方のクラスで必要な API にアクセスするために使用)が必要なため、特定の状況で Skia が太字情報を失い、太字フォントが機能しなくなります。これは 問題 #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 は重みの問題に気づき、サイズ変更の別の修正を行いました。元の CTFont から直接新しい CTFont を作成し、CoreText の古い(ドキュメントに記載されていない)属性を使用して光学サイズを直接制御します。これにより、10.11 で動作が維持され、他の問題(光学サイズを明示的にデフォルト値に設定するなど)も修正されます。

ただし、これにより、フォント内の CoreText の「マジック」がより多く保持されます。そのうちの 1 つは、trak テーブル(Chromium が文書化されていない別の属性によってすでに抑制しようとしていたアプリケーション)以外の方法で、グリフの進歩を微調整しているようです。

CGFont はこのような「魔法」を一切行いません。Chromium は CTFont から CGFont を取得し、それを使用して前払いを取得できるでしょうか?残念ながら、CoreText は他の方法でもフォントを変更することが知られているため、この方法は機能しません。たとえば、小さな絵文字が実際にリクエストしたよりも少し大きくなります(サイズを少し大きくします)。CGFont はこれを認識しないため、1 つのサイズで測定されるが CoreText によってある程度大きく描画されるため、sbix ベースの絵文字が互いに近づきすぎてしまいます。Chromium は CTFont の進歩を望んでいますが、トラッキングなしで、できれば他の手間をかけずに進歩することを望んでいます。

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

修正方法

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

system-ui とそのすべてのフォントの太さ、リストのバリエーション。以前は動作しなかった半分も、正常に動作するようになりました。

なお、Skia でこの問題を完全に修正し、HarfBuzz を介した現在の修正ではなく、Skia を使用してシステム フォント メトリックを取得できるようにするための Skia の問題 #10123 が引き続き存在します。