画面が「チラつく」正体、教えます。Webフォントと `font-display` の深淵
現場でフロントエンドをしていると、必ず一度は頭を抱える問題がある。そう、「Webフォントの読み込み待ち」だ。
通信環境が悪い場所でページを開くと、一瞬テキストが消えたり、突然フォントがガクッと切り替わったりする。あれ、ユーザー体験としては最悪だよな。でも、ブラウザのレンダリングエンジン側から見れば、あれは「死ぬ気でフォントを待っている(あるいは諦めて表示している)」という必死の挙動なんだ。
今日は、ブラウザが裏側で何を考え、どうやってテキストをスクリーンに叩き込んでいるのか。その心臓部である `font-display` の挙動を、泥臭い実務の視点で解き明かしていくぞ。
—
ブラウザは「フォントがない」とき、どう動くのか
まず前提として、ブラウザにとって「Webフォント」は外部リソースだ。HTMLがパースされ、DOMツリーとCSSOMツリーが合体して「レンダーツリー」が構築される。しかし、フォントファイルが届いていないと、ブラウザは文字を表示するための「筆」を持っていない状態になる。
ここでブラウザがとる行動は、実は2種類しかない。
1. 「筆が来るまで隠す」(FOIT: Flash of Invisible Text)
2. 「とりあえず手持ちの筆(システムフォント)で書いて、後で書き直す」(FOUT: Flash of Unstyled Text)
この挙動を制御するのが、CSSの `font-display` プロパティだ。
—
`font-display` の4つの選択肢:現場での賢い使い分け
`@font-face` で指定するこのプロパティ、適当に `swap` にしていればいいと思ったら大間違いだ。それぞれの「性格」を理解して使い分けよう。
1. `block`(デフォルトの裏側)
ブラウザはフォントが読み込まれるまで、約3秒間、文字を一切表示しない。
- 現場の評価: ほぼNG。真っ白なページはユーザーに「バグった」と思われる。
2. `swap`(王道)
即座にシステムフォントを表示し、Webフォントが届いた瞬間に差し替える。
- 現場の評価: 最も推奨される。ただし、フォントの横幅が変わると「レイアウトシフト(CLS)」が起きるから、`size-adjust` 等の調整が必須だ。
3. `fallback`(妥協案)
約100msだけ隠し、その後読み込めていなければシステムフォントを使う。読み込みが遅すぎると、Webフォントが届いても切り替わらないこともある。
- 現場の評価: 「読み込みが遅いなら最初から見せろ」という割り切りが必要な、ロゴや見出し向け。
4. `optional`(職人の選択)
100ms待って読み込めなければ、そのページ表示中はもうWebフォントを使わない。キャッシュにあれば即座に使う。
- 現場の評価: 極めて高いUX。フォントの切り替わりによるチラつきを徹底的に排除したい場合に使う。
—
実践:CLSを最小化する「神セットアップ」
`font-display: swap` を使うと、フォントが切り替わった瞬間にテキストの幅が変わり、画面がガクッとズレる。これを防ぐために、モダンブラウザが提供している `size-adjust` を使おう。
以下のコードは、Webフォントが読み込まれるまでの「システムフォント」と「Webフォント」の見た目を極力近づけるためのテンプレートだ。
/ Webフォントの定義 /
@font-face {
font-family: ‘MyCustomFont’;
src: url(‘/fonts/my-font.woff2’) format(‘woff2’);
font-display: swap; / 読み込み中はシステムフォントで表示 /
}
/
- 重要なトリック:システムフォント側でサイズや間隔を調整し、
- Webフォントと極力同じ見た目になるように「偽装」する
/
.body-text {
font-family: ‘MyCustomFont’, sans-serif;
}
/
- 読み込み後のガタつきを防ぐには、CSSの @font-face 内で
- size-adjust や ascent-override を使って、
- システムフォントとWebフォントの高さや幅を揃えるのが今のトレンドだ。
/
@font-face {
font-family: ‘MyCustomFont’;
src: url(‘/fonts/my-font.woff2’) format(‘woff2’);
/ システムフォントとの見た目の差異を埋める魔法のプロパティ /
size-adjust: 95%;
ascent-override: 90%;
font-display: swap;
}
—
チーフアーキテクトからの助言
最後に一つだけ、大事なことを伝える。
「Webフォントはあくまで『装飾』である」という意識を持ってくれ。
回線が細いモバイル環境で、巨大なWebフォントを読み込ませるためにコンテンツの表示を遅らせるのは、フロントエンドエンジニアとしては失格だ。
1. まず `font-display: swap` を基本にする。
2. CLS(レイアウトシフト)が起きるなら、`size-adjust` で追い込む。
3. それでも遅延が気になるなら、`preload` で優先度を上げるか、そもそも「Webフォントを使わない」という勇気を持つ。
ブラウザの裏側を覗くと、彼らが「いかにユーザーを待たせずにコンテンツを見せるか」に腐心していることがよく分かるはずだ。その仕組みを理解してコードを書けば、君の作るUIはもっと速く、もっと美しくなる。
現場からは以上だ。何か詰まったら、いつでも聞いてくれ。

コメント