Google Fontsで学ぶWebフォントの基本 第3回 font-displayとフォント読み込み中の表示

Webフォントの読み込み中にテキストがどう表示されるかを制御するfont-displayプロパティについて、FOIT/FOUTの概念と併せて解説します。

発行

著者 藤田 智朗 フロントエンド・エンジニア
Google Fontsで学ぶWebフォントの基本 シリーズの記事一覧

前回まで

前回は、preconnectによるWebフォントの読み込み最適化と、フォントに必須のCORS・crossorigin属性について解説しました。

今回は、Webフォントの読み込みが完了するまでの間、テキストがどのように表示されるかという問題に焦点を当てます。Webフォントはネットワーク経由で取得するため、表示までにどうしても時間がかかります。その間のテキスト表示を制御するのがfont-displayプロパティです。

フォント読み込み中に何が起きるか

Webフォントを使う場合、ブラウザはフォントファイルをダウンロードする必要があります。このダウンロードが完了するまでの間、ページ上のテキストはどうなるのでしょうか。

ブラウザの挙動には、大きく分けて2つのパターンがあり、それぞれの現象には名前が付けられています。

FOIT(Flash of Invisible Text)

FOIT(Flash of Invisible Text)は、Webフォントの読み込みが完了するまでテキストが表示されない現象です。ブラウザはフォントが利用可能になるまでテキストを非表示にし、フォントが読み込まれた時点でテキストを描画します。

ユーザーから見ると、ページを開いた直後にテキスト部分が空白になっており、しばらくしてから突然テキストが表示されるという体験になります。特にネットワークが遅い環境では空白の時間が長くなり、コンテンツが読めない状態が続くことになります。

FOUT(Flash of Unstyled Text)

FOUT(Flash of Unstyled Text)は、Webフォントの読み込みが完了するまでフォールバックフォント(システムフォントなど)でテキストを表示し、フォントが読み込まれた時点でWebフォントに切り替わる現象です。

ユーザーから見ると、最初はシステムフォントでテキストが表示され、途中でWebフォントに切り替わるという体験になります。テキストは最初から読めますが、フォントの切り替え時にレイアウトが変化することがあります。

どちらが好ましいか

FOITとFOUT、どちらが好ましいかはケースによりますが、多くのWebサイトではFOUT、つまりフォールバックフォントで先にテキストを表示するほうが好ましいとされています。理由は明確で、テキストが読めない状態よりも、見た目が多少異なっていてもテキストが読める状態のほうがユーザーにとって有益だからです。

ただし、FOUTにも問題があります。フォントが切り替わる際に文字の幅や高さが変わることで、レイアウトがガタッとずれる「レイアウトシフト」が発生します。これはCore Web VitalsのCLS(Cumulative Layout Shift)にも影響するパフォーマンス指標の1つです。

font-displayプロパティと各値

前節で見たFOITやFOUTは、ブラウザがWebフォントの読み込み中にどう振る舞うかによって生じる現象でした。この挙動を開発者側から制御できるのがfont-displayプロパティです。@font-face内で指定し、フォントの読み込み中にブラウザがどのようにテキストを表示するかを決定します。

@font-displayプロパティ

@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/...) format('woff2');
}

フォント表示のタイムライン

font-displayの各値を理解するために、ブラウザがフォントを読み込む際のタイムラインを整理します。ブラウザはフォントの読み込みを3つの期間に分けて管理しています。

  1. ブロック期間(block period):この期間中、ブラウザはテキストを非表示(透明なテキスト)で描画します。フォントがこの期間中に読み込まれれば、すぐにWebフォントで表示されます。
  2. スワップ期間(swap period):この期間中、ブラウザはフォールバックフォントでテキストを表示します。フォントがこの期間中に読み込まれれば、Webフォントに切り替わります。
  3. 失敗(failure):スワップ期間を過ぎてもフォントが読み込まれなかった場合、ブラウザはフォントの読み込みを諦め、フォールバックフォントのまま表示を続けます。

font-displayの各値は、このブロック期間とスワップ期間の長さを変えることで、表示の挙動を制御します。ブロック期間が長ければFOIT的な挙動に、短ければFOUT的な挙動になります。

font-display: auto

auto設定

font-display: auto;

ブラウザのデフォルトの挙動に従います。多くのブラウザではblock(次項参照)に近い挙動になります。数秒程度テキストを非表示にします。明示的に指定しない場合はこの値が使われます。「数秒」というのはブラウザや実装によって異なるため、あくまで目安です。

font-display: block

block設定

font-display: block;
  • ブロック期間:短い(目安:数秒程度)
  • スワップ期間:無期限

フォントの読み込み中はテキストを非表示にし、読み込まれたらWebフォントで表示します。3秒以内にフォントが読み込まれなかった場合はフォールバックフォントが表示され、その後フォントが読み込まれ次第Webフォントに切り替わります。FOITに近い挙動です。

アイコンフォントのように、フォールバックフォントで表示すると意味が通じなくなるケースではblockが適切です。

font-display: swap

swap設定

font-display: swap;
  • ブロック期間:極めて短い(目安:ほぼ0)
  • スワップ期間:無期限

フォントの読み込み中はすぐにフォールバックフォントでテキストを表示し、読み込みが完了したらWebフォントに切り替えます。FOUTの挙動そのものです。

テキストの可読性を最優先する場合に適しており、Google Fontsではこの値がデフォルトで使われています。

font-display: fallback

fallback設定

font-display: fallback;
  • ブロック期間:極めて短い(目安:約100ms程度)
  • スワップ期間:短い(目安:数秒程度)

swapと似ていますが、スワップ期間に制限があります。フォントが約3秒以内に読み込まれなかった場合、フォールバックフォントのまま表示を続けます。ページ表示の安定性(レイアウトシフトの抑制)と、フォントの適用のバランスをとった設定です。

font-display: optional

optional設定

font-display: optional;
  • ブロック期間:極めて短い(目安:約100ms程度)
  • スワップ期間:なし

ブロック期間内にフォントが読み込まれなかった場合、そのページ表示ではWebフォントを使いません。ブラウザはバックグラウンドでフォントをダウンロードし、次回以降のページ表示でキャッシュから使用します。

レイアウトシフトを完全に防ぎたい場合に適しています。初回アクセスではWebフォントが表示されないことがほとんどですが、2回目以降はキャッシュから即座に表示されます。

各値の比較

以下の表にまとめます。

ブロック期間 スワップ期間 特徴
auto ブラウザ依存 ブラウザ依存 デフォルト挙動
block 短い(目安:数秒程度) 無期限 FOIT寄り
swap ほぼ0(目安) 無期限 FOUT(テキスト優先)
fallback 極めて短い(目安) 短い(目安:数秒程度) バランス型
optional 極めて短い(目安) なし レイアウトシフト防止

日本語でswapが不自然になりやすい理由

ここまでfont-displayの各値を見てきました。では、日本語Webフォントにはどの値が適しているのでしょうか。テキストの可読性を優先するswapが広く推奨されていますが、日本語フォントではswapが不自然な体験を生みやすいという側面があります。

フォールバックとの差が大きい

日本語のフォールバックフォントは、一般的にOSのシステムフォント(macOSではヒラギノ角ゴ、Windowsではメイリオや游ゴシックなど)です。これらとWebフォント(例:Noto Sans JP)では、文字の幅や高さ、行間のバランスが異なります。

英語フォントであれば、システムフォント(Arial、Helveticaなど)とWebフォントの差は比較的小さく、システムフォントからWebフォントへの切り替わりが気になりにくいことが多いです。しかし日本語フォントは文字ごとの幅の差やメトリクスの違いが大きく、切り替え時のレイアウトシフトが目立ちやすくなります。

補足:メトリクス

メトリクスとは、フォントにおけるレイアウトのためのサイズ全般を指します。代表的なものに、ベースラインを基準に上方の高さを示すアセンダー、下方の高さを示すディセンダーなどがあります。

読み込み時間が長い

第1回で解説したとおり、Google Fontsなどの配信サービスでは日本語フォントがサブセットに分割されていることが多いですが、それでも英語フォントと比べて取得するファイルの総量は多くなります。フォントの読み込みに時間がかかるほど、フォールバックフォントで表示される時間が長くなり、切り替わりの違和感が増します。

視覚的な影響

結果として、日本語Webフォントにswapを指定した場合、次のような体験になることがあります。

  1. ページを開くとシステムフォントでテキストが表示される
  2. 数百ミリ秒〜数秒後にWebフォントに切り替わる
  3. 切り替え時に文字の幅が変わり、行の折り返し位置がずれる
  4. レイアウトがガタッと動く

特に見出しなど大きなテキストでは、この切り替わりが顕著に目立ちます。

Google Fontsがdisplay=swapをデフォルトにしている理由

Google FontsのURLには&display=swapというパラメータを追加できます。

font-displayをswapに設定するパラメータ

https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap

このパラメータを付けると、Google Fontsが返すCSSの@font-facefont-display: swapが自動的に追加されます。

パラメータによって設定されたCSS

@font-face {
  font-family: 'Noto Sans JP';
  font-display: swap;
  /* ... */
}

実際に、執筆時点(2026年2月)でGoogle FontsのUIから埋め込みコードを取得すると、デフォルトで&display=swapが含まれています。これは、フォント読み込み中もテキストを表示し続けることで、ユーザーがコンテンツをすぐに読み始められるようにするためと考えられます。

ただし前述のとおり、日本語フォントではswapによるレイアウトシフトが大きくなりやすいため、fallbackoptionalのほうが適切なケースもあります。displayパラメータにはswap以外の値も指定できるので、用途に応じて選択しましょう。

font-displayをoptionalに設定するパラメータ

https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=optional

まとめ

今回は、Webフォントの読み込み中の表示を制御するfont-displayプロパティについて解説しました。

  • FOITはフォント読み込み中にテキストが見えない現象、FOUTはフォールバックフォントからWebフォントに切り替わる現象
  • font-displayプロパティでブラウザの挙動を制御できる
  • swapはテキストの可読性を優先し、Google Fontsでもデフォルトで使われている
  • 日本語フォントではswapによるレイアウトシフトが目立ちやすい
  • fallbackoptionalはレイアウトシフトを抑制するが、Webフォントが表示されないケースがある

次回からは、これらの知識を踏まえて、Next.jsのnext/font/googleがWebフォントの読み込みをどのように最適化しているかを見ていきます。font-display: swapが自動的に設定される仕組みや、セルフホスティングによる配信最適化について解説します。