定義
ウェブフォント(ブラウザに標準内蔵されておらず、CSS @font-face で別途ダウンロードする書体)を使いたいが、フォントが遅く届いて画面が一度揺れるのを防ぎたいときに使う CSS プロパティが font-display: optional だ。
正確には、font-display はウェブフォントがまだ来ていないときにブラウザがどう振る舞うかを決める方針だ。optional 値は「短い時間(block period、ブラウザがフォントを待つ猶予時間、通常 100ms 前後)内に来なければ、そのまま代替フォント(fallback)で確定し、このページではウェブフォントに差し替え(swap)しない」という意味だ。目的はレイアウトが揺れないようにすること、すなわち CLS(Cumulative Layout Shift、画面要素が予期せずずれた度合いを測る Core Web Vitals 指標)を下げることだ。
なぜ必要か
デフォルトに近い swap を使うと、こういうことが起きる: ページが代替フォントで先に描かれ、少し後にウェブフォントが届くとその書体に差し替える。ところが二つの書体は文字の幅・高さ(glyph metrics、文字一つが占める寸法)が違うため、差し替える瞬間にタグ(pill・badge)や本文の改行位置がずれる。ユーザーの目には「読み終えようとしたら文字がぴょこっと動く」現象に見え、これが CLS スコアを削る。
文書・リストのように文字が多い UI では、ブランドフォントを 100% 見せることより、最初の画面が揺れないことのほうがユーザー体験と Core Web Vitals(Google が定義した中核的なウェブ性能指標)に有利な場合が多い。optional はそのトレードオフを「揺れなし」側に固定する。
動作原理
- ブラウザが短い block period の間ウェブフォントのロードを待つ。
optional: 期間内に届かなければ今回の訪問(navigation)ではウェブフォントを諦め、代替フォントで確定する。- 代替フォントスタック(fallback stack、
font-familyに並べた候補書体の順序)が最後までレンダリングされるので、途中で寸法が変わらない。 - 遅いネットワークでテストしたとき、CLS が 0 に近く保たれるかを確認する。
実務での適用
- 本文・mono バッジ・大きな見出し(display)にそれぞれ
optionalを適用する。ただし画面最上部の代表領域(hero、最初の画面で最も目立つ大きな領域)だけは preload(ブラウザに「このフォントを先に受け取っておけ」と優先度を上げる<link rel="preload">)とswapを例外にできる。 - 代替フォントに
size-adjust(代替フォントの文字サイズをウェブフォントに合わせて比率調整する@font-faceプロパティ)を載せると、optionalでウェブフォントを諦めても文字寸法がウェブフォントに近く保たれる。 - 遅いネットワークを模す throttling(ブラウザ開発者ツールで Slow 4G などに速度を強制的に下げること)状態で Lighthouse を使い、CLS が再び悪化しないか回帰確認する。
トレードオフ
optionalはブランドフォントが実際に見える比率を下げる — hero 領域だけ例外で活かせる。- 初回訪問 + 遅い 3G では代替フォントだけを見ることになりうる — 揺れをなくす代償として受け入れるトレードオフだ。
使ってはいけない場合
- ブランドタイポグラフィが製品アイデンティティの核心で、CLS よりその書体を 100% 見せることのほうが重要なとき。
よくある間違い
optionalを掛けたのに代替フォントスタックがsystem-ui一つだけ — ウェブフォントの代わりに見える書体の可読性が落ちる。swapとoptionalを役割別の方針なしに混ぜて使い、あるテキストは揺れ、あるテキストは揺れない。
関連概念
- [[cls-skeleton-layout-reservation]]
- [[critical-rendering-path]]