フォントの読み込み
Webフォントの読み込みがCLSやLCPなどのCore Web Vitalsに与える影響、font-displayの戦略、フォントのプリロード、フォント切り替えによるレイアウトシフトの抑え方を解説します。
カスタムWebフォントは、テキストをその書体で描画する前にダウンロードが必要な外部ファイルです。その間に何を表示するかを、主にCSSのfont-displayプロパティで決めます。この挙動は、レンダリングを妨げるフォントが最大のテキスト表示を遅らせるLCPと、代替フォントからWebフォントへの切り替えが配置を動かすCLSに影響します。FOITとFOUTという2つの基本挙動には、それぞれ弱点があります。重要なフォントをプリロードする、font-display: optionalまたはswapを意図的に使う、代替フォントのメトリクスを合わせる、あるいはカスタムフォントを使わないことが確実な対策です。フォント読み込み自体は直接のランキング要因ではなく、ページエクスペリエンスのシグナルであるCLS/LCPに影響します。
この主張の根拠 The CSS Font Loading API exposes font loading state and control to documents. 対象範囲: Current official or standards documentation. 信頼度: 高 · 検証日: MDN: CSS Font Loading API この主張の根拠 font-display controls how a font face is displayed while it downloads and when fallback is used. 対象範囲: Current official or standards documentation. 信頼度: 高 · 検証日: MDN: font-display要点 — カスタムWebフォントは、ブラウザがその書体でテキストを表示する前にダウンロードしなければならないファイルです。待っている間、ブラウザはテキストを隠すか、代替フォントを表示して後から切り替えます。どちらもページを遅くしたり、見た目を跳ねさせたりする可能性があります。この挙動はCSSの1行(
font-display)で制御でき、プリロードでフォントの取得も早められます。カスタムフォントが不要なら、システムフォントには読み込みも切り替えもありません。
フォント読み込みとは
ブランドフォントやGoogle Fontなど、訪問者の端末にないカスタムフォントを使う場合、ブラウザはそのフォントファイルを取得してからテキストを描画します。ダウンロードには時間がかかるため、ブラウザはその間に何を表示するかを決める必要があります。
基本的な選択肢は2つで、どちらにも少し厄介な名前があります。
- FOIT(Flash of Invisible Text): カスタムフォントが届くまでテキストを隠します。テキストがある場所は空白に見え、到着後に突然表示されます。
- FOUT(Flash of Unstyled Text): 通常の代替フォントをすぐ表示し、読み込み後にカスタムフォントへ切り替えます。テキストはすぐ読めますが、2つのフォントの寸法が違うと切り替え時に目に見えて「跳ねる」ことがあります。
SEOで重要な理由
どちらにも代償があります。FOITは主要テキストの表示を遅らせ、Largest Contentful Paint (LCP)を悪化させる可能性があります。FOUTはフォント切り替え時にレイアウトシフトを起こし、**Cumulative Layout Shift (CLS)**を悪化させる可能性があります。LCPとCLSはいずれもCore Web Vitals であり、Googleがページエクスペリエンスの一部として使う実ユーザー指標です。つまりフォント読み込みは、単なるデザイン上の細部ではなく、テクニカルSEOで調整できる要素です。
シンプルな対策
- 可能ならシステムフォントを使う。 ダウンロードがないため、遅延も切り替えもありません。最も確実な対策です。
- カスタムフォントが必要なら
font-displayを設定する。font-display: swap(またはoptional)を追加すると、待機中にテキストを非表示にしないようブラウザへ指示できます。 - 重要なフォントをプリロードする。
<link rel="preload">タグは、後で検出されるのを待たず、フォントを早期に取得するようブラウザへ伝えます。
font-displayの値一覧、プリロード+optionalの組み合わせ、代替フォントのメトリクス調整、Google Fontsとセルフホスティングの比較まで知りたい場合は、上級タブへ切り替えてください。
この主張の根拠 The CSS Font Loading API exposes font loading state and control to documents. 対象範囲: Current official or standards documentation. 信頼度: 高 · 検証日: MDN: CSS Font Loading API この主張の根拠 font-display controls how a font face is displayed while it downloads and when fallback is used. 対象範囲: Current official or standards documentation. 信頼度: 高 · 検証日: MDN: font-display要点 — カスタムWebフォントはレンダリングに影響する外部リソースです。レンダリングを妨げるフォントが最大のテキスト要素を遅らせればLCPに、代替フォントからWebフォントへの切り替えがレイアウトを再配置すればCLSに影響します。基本挙動のFOIT(読み込みまで非表示)とFOUT(代替フォントを表示してから切り替え)は、異なる形で問題になります。主な調整手段は
font-displayです(swapはFOUTを確実に起こし、optionalは約100msの猶予後に使用フォントを確定して、その後の切り替えをなくします)。プリロードはフォントの検出遅延を解消し、**プリロード+font-display: optional**はGoogleのエンジニアリング記事がレイアウトのがたつきをなくす方法として特に挙げています。ただしLighthouseのfont-displayチェックに合格してもCLSは直りません。メトリクスの近い代替フォント(またはsize-adjust/ascent-override)が必要です。フォント読み込み自体は直接のランキング要因ではなく、ページエクスペリエンスのシグナルであるCLS/LCPに作用します。
フォントが特殊な理由
多くのパフォーマンス問題はバイト数に関係します。画像が大きすぎる、スクリプトがメインスレッドを塞ぐ、といったものです。フォントはある一点でさらに厄介です。外部リソースであるうえに、テキストのメトリクスも変えるからです。そのため、テキストの描画を遅らせる(LCPの問題)ことと、表示後にテキストの大きさや形を変える(CLSの問題)ことを同時に引き起こします。
この話全体の土台となる、ブラウザの2つの基本挙動を押さえておきましょう。
- FOIT(Flash of Invisible Text): カスタムフォントが読み込まれるかタイムアウトするまで、そのフォントのテキストを非表示で描画します。従来、多くのブラウザでブロック期間は最大約3秒でした。
- FOUT(Flash of Unstyled Text): 代替フォントをすぐ表示し、Webフォントが読み込まれた時点で置き換えます。
FOITは「きれい」(跳ねない)に見える一方、描画遅延の危険があります。FOUTは速く(テキストがすぐ)感じられる一方、切り替え時のレイアウトシフトが問題になります。どちらも自動的に安全ではない、というのが核心です。
処理を別々の段階に分けて考えることも重要です。ある段階の成功が次の段階を保証するとは限りません。@font-face規則は書体を宣言するだけで、ブラウザが実際のフォントファイルを取得するのは、その書体に一致するスタイル付きテキストがページ上で必要になったときです(宣言とマッチングは取得とは別の段階です)。フォントを別オリジンから配信する場合、その取得はCORSの対象です。スタイルシートが問題なく読み込めても、フォントのレスポンス自体に適切なクロスオリジン許可があるとは限らず、ヘッダーが欠けるとフォントは表示されないまま静かに失敗します。さらに、取得に成功しても見た目が安定する保証はありません。コールドキャッシュ、ウォームキャッシュ、既にキャッシュ済みという状態ごとに検出や切り替えのタイミングが変わるため、DevToolsで再読み込みを1回試すだけでは初回訪問者の見え方は分かりません。
フォントがLCPに与える影響
ページで最も大きく見える要素が大きな見出しやヒーロー領域の段落などのテキストなら、そのテキストが使うフォントはLCP経路の一部になり得ます。web.devのLCPガイダンスによれば、ページにLCPリソースがある場合、それは画像かWebフォントのいずれかです。テキストを非表示にするレンダリング阻害フォント(FOIT)は、フォントが届くまでLCPを遅らせます。
対策は明快で、Googleが直接示しています。web.devのOptimize Largest Contentful Paint には次のようにあります。
“If you set a
font-displayvalue of anything other thanautoorblock, then text will always be visible during load, and LCP won’t be blocked on an additional network request.” (翻訳) 「font-displayにautoまたはblock以外の値を設定すると、読み込み中もテキストは常に表示され、追加のネットワーク要求によってLCPが妨げられることはありません。」 — web.dev
つまり、swap、fallback、optionalはいずれも読み込み中のテキストを表示し、LCPがフォント要求に拘束されるのを防ぎます。
フォントがCLSに与える影響
CLSは切り替えによって生じます。代替フォントとWebフォントでは文字幅や行の高さがほぼ必ず異なるため、一方を他方に置き換えるとテキストが再配置され、その下のすべてが動きます。これがレイアウトシフトです。
直感に反し、多くの人が見落とす点があります。FOITもCLSを引き起こします。 非表示のテキストも代替フォントのメトリクスで配置されるため、切り替えればやはり動きます。web.devのOptimize Cumulative Layout Shift には次のようにあります。
“Both approaches can cause layout shifts. Even if the text is invisible, it’s still laid out using the fallback font, so when the web font loads, the text block and the surrounding content shift” (翻訳) 「どちらの方法もレイアウトシフトを引き起こす可能性があります。テキストが非表示でも代替フォントを使って配置されるため、Webフォントが読み込まれるとテキストブロックと周囲のコンテンツが移動します。」 — web.dev
同じページでは2つの挙動を次のように説明しています。
“The fallback font is swapped with the web font, incurring a Flash of Unstyled Text (FOUT). ‘Invisible’ text is displayed using the fallback font until a web font is available and the text is made visible (FOIT—flash of invisible text).” (翻訳) 「代替フォントがWebフォントに置き換わることで、Flash of Unstyled Text(FOUT)が発生します。Webフォントが利用可能になってテキストが表示されるまで、『非表示』のテキストは代替フォントで表示されます(FOIT、flash of invisible text)。」 — web.dev
私もAhrefsのCumulative Layout Shift の記事で、より平易に同じことを述べています。フォントが読み込まれたり変わったりすると、FOITまたはFOUTという目立つシフトが起こります。これは、寸法を指定していない画像や読み込み後に挿入されるコンテンツと並び、現実によくあるCLS原因の一つです。
font-displayプロパティ
font-displayは@font-faceの記述子で、ブロック期間(フォントを待つ間にテキストを隠す時間)とスワップ期間(ブロック期間後も、到着したWebフォントへ切り替える時間)という2つの時間枠を制御します。web.devのBest Practices for Fonts によると次のとおりです。
| 値 | ブロック期間 | スワップ期間 |
|---|---|---|
auto | ブラウザ依存 | ブラウザ依存 |
block | 2〜3秒 | 無限 |
swap | 0ms | 無限 |
fallback | 100ms | 3秒 |
optional | 100ms | なし |
Google自身の文書が仕様の参照先としてリンクするMDNのfont-displayリファレンス は、簡潔に定義しています。swapは極めて短いブロック期間と無限のスワップ期間を持ち、optionalは極めて短いブロック期間を持つ一方、スワップ期間はありません。この「スワップ期間なし」こそoptionalの要点です。ブロック期間が終わると、その時点で使われているフォントが維持され、後から切り替わってレイアウトを動かすことがありません。
表の数値には注意が必要です。CSS仕様自体が定義するのは、short、extremely small、infinite、noneというブロック/スワップの期間分類だけで、正確な時間はブラウザに委ねられています。上のミリ秒・秒の値はweb.devが文書化したChromiumの挙動であり、ブラウザ横断の保証ではありません。仕様上の約束ではなく目安として扱い、実際にテストするブラウザ/バージョンの現行値を確認してください。
どのコンテンツにどの値を使うか。 web.devは値を使い分けられると助言しています。ブランドフォントの表示が重要で短いシフトを許容できるブランド要素や視覚的に特徴のある要素にはswap、CLSへの影響を優先しシフトを避けたい本文にはoptionalを使います。サイト全体に反射的に同じ値を設定しない、実用的な目安です。
フォントのプリロード
フォント要求は遅く検出されます。ブラウザが必要性を知るのは、CSSを解析し、ページ要素に@font-face規則を照合し、その要素が表示されると判断した後です。そこで初めてダウンロードが始まります。<link rel="preload">はこの経路を短縮します。
<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>これは、フォントが後で検出されるのを待たず、他の処理と並行して直ちに取得を始めるようブラウザへ伝えます。Bingのエンジニアリングチームも、自社検索ページでまさにこの仕組みを説明しています(詳細は「引用」タブ)。<head>内のプリロードタグがすぐにフォントのダウンロードを開始し、タグがなければブラウザはCSSを解析して一致する要素を見つけるまでフォントを取得しません。
Google自身の記事が挙げる最も強力な組み合わせは、**プリロード+font-display: optional**です。web.devのoptionalフォントのプリロードでレイアウトシフトとFOITを防ぐ は、<link rel="preload">とfont-display: optionalの併用を、カスタムフォント描画時のレイアウトのがたつきを確実になくす最も効果的な方法としています。またChromeではバージョン83以降、optionalフォントのプリロード時に起きていたレイアウトシフトが解消されたと述べています。プリロードは約100msの枠内にフォントが届く可能性を最大化し、間に合わなくてもoptionalがシフトを防ぎます。
プリロードしない方がよい場合。 プリロードは無料ではありません。web.devは、フォントを早期に検出させる効果が高い一方、他のリソース読み込みに使うブラウザ資源を奪うと警告しています。ファーストビューで本当に必要な1〜2個だけをプリロードしてください。所有するすべてのウェイトをプリロードすると、より重要なリソースが不足し、ページ全体が遅くなることがあります。
プリロードが実際に再利用されることを確認する。 プリロードが役立つのは、ブラウザが実際のフォント要求と一致させられる場合だけです。href、as="font"、type、crossoriginのモードは、CSSの@font-face規則が最終的に要求する内容と一致しなければなりません。違えば高速化どころか「unused preload」警告と無駄な2回目のダウンロードが発生します。プリロードはunicode-rangeの選択を迂回し、そのページに不要なサブセットを取得する場合もあります。DevToolsのNetworkパネルで一致を確認し、プリロードから始まった要求が1件だけで、2件になっていないことを確かめてください。
シフト自体を直す:代替フォントのメトリクスを合わせる
落とし穴があります。Lighthouseのfont-displayチェックに合格しても、CLSは直りません。GoogleのLighthouse文書は、一時的なシステムフォントがカスタムフォントに置き換わると、FOITとFOUTがCLSに与える影響は同じだと明記しています。swapはテキストを表示し(LCPと「非表示テキスト」監査には有効)、切り替えによるシフトは残します。
実際に切り替わるときのシフトをなくすには、代替フォントとWebフォントが同じ空間を占めるようにします。手段は2つです。
font-familyスタックに、妥当な代替がない単独のカスタムフォント名ではなく、メトリクスが近いシステムフォントを選びます。代替フォントの文字幅と行高がWebフォントに近いほどシフトは小さくなります。@font-face規則でsize-adjust、ascent-override、descent-override、line-gap-overrideを使い、Webフォントのメトリクスを上書きして代替フォントのボックスに合わせます。web.devはこれらの記述子を列挙しており、徹底したい場合はSmashing MagazineのCSSフォント記述子の詳細解説 が参考になります。
4つの記述子はそれぞれ別のメトリクスを調整し、現在のブラウザ対応状況も記述子ごとに異なります。1つに依存する前に互換性を確認してください。実際に配信するウェイト、スタイル、文字体系でも検証が必要です。標準ウェイトのラテン文字で確認した修正が、太字、斜体、非ラテン文字でも同じように機能するとは限りません。
DebugBearのFixing Layout Shifts Caused by Web Fonts は、影響の計測、問題フォントの特定、font-displayの適用、より良い代替フォントの選択、フォントメトリクスの調整までを通して説明する優れた手引きです。
Google Fontsとセルフホスティング
font-displayを制御するためにセルフホスティングする必要はありません。Google Fonts CSS2 API はdisplayクエリパラメータを受け付け、https://fonts.googleapis.com/css2?family=Roboto&display=swap のように配信される@font-face規則へ直接font-displayを設定できます。Addy OsmaniのGoogle Fontsへのfont-display導入記事 では、以前はGoogle Fontsでfont-displayを指定する唯一の方法がセルフホスティングだったものの、この変更で不要になった経緯を説明しています。
セルフホスティングにはなお1つの強みがあります。fonts.googleapis.comとfonts.gstatic.comへの追加のDNS検索と接続をなくせることです。これは実際の遅延コストであり、Google Fontsを使う場合にそれらのオリジンへのpreconnectリソースヒント が役立つ理由でもあります。接続のオーバーヘッドと利便性を比較し、「Googleのものだから問題ない」とは考えないでください。コピーしたGoogle Fontsの埋め込みも、レンダリングを妨げるスタイルシート要求とフォント要求であり、古い埋め込みにはdisplay値がない場合もあります。
両者に普遍的な勝者はいません。実際に配信する文字体系とウェイト、キャッシュ設定、フォントのライセンス条件で決まります。チュートリアルの推奨をそのまま採用せず、自分のページで比較してください。
可変フォント
可変フォントは、標準、太字、幅狭、斜体など多くのウェイトやスタイルを、調整可能な軸を持つ1ファイルにまとめます。複数のバリエーションを実際に使うなら、6件の要求を1件にでき、全体として有利な場合があります。ただし完全な可変フォントは静的な1ウェイトより単一ファイルが大きいため、1ウェイトしか描画しないなら、かえって遅くなる可能性があります。使う軸と文字へサブセット化し、圧縮されたWOFF2で配信し、ライセンスも確認してください。すべてのフォントメーカーがサブセット化やセルフホスティングを許可しているわけではありません。
そもそものファイルを小さくする
ここまでの対策は、フォントがいつ読み込まれるかを管理します。読み込むもの自体も小さくできます。フォントのサブセット化は使わないグリフを取り除き(ラテン文字だけのサイトにキリル文字やCJKの範囲は不要です)、WOFF2は十分に圧縮された配信形式です。小さいフォントファイルほどoptionalの時間枠内に届きやすく、LCPを妨げにくくなります。サブセット化と圧縮はfont-displayやpreloadを補完する手段であり、代替ではありません。
ただし、唯一の「正しい」サブセットや普遍的なバイト削減率はありません。対象ユーザーが実際に必要とする文字体系、文字、ウェイトによって変わります。他人の事例やベンチマークで見た数値は自分のページへの保証ではないため、変更前後のフォント要求を計測してください。
ランキング要因なのか
正確に言えば、フォント読み込みは直接のランキング要因ではありません。影響するCLSとLCPはCore Web Vitalsであり、Googleのページエクスペリエンスシグナルの一部です。そしてページエクスペリエンスは、軽量なタイブレーカーのようなシグナルです。関連性と品質が支配的で、優れたページと劣ったページを逆転させるものではなく、他の点で同程度の結果を比較するときに役立ちます。したがって正直な説明は、font-displayの値だけで順位が上がるからではなく、2つのランキング入力にも影響する本物のユーザー体験問題だからフォント読み込みを直す、となります。
私の見解
AhrefsのCLS とLCP のガイドでたどり着いた優先順位は同じで、今も変わりません。システムフォントを使えるなら使ってください。読み込みがなく、遅延もシフトを起こす変更もありません。カスタムフォントがどうしても必要なら、CLSを最小化する現在の最良の方法は、<link rel="preload">(できるだけ早く取得)とfont-display: optional(短い読み込み時間枠)を組み合わせることです。間に合わなければページはデフォルトフォントを表示し、カスタムフォントはキャッシュされて次回以降に表示されます。プリロード、次にoptional、そして最善はカスタムフォントを使わないこと。これが優先順位のすべてです。
AI要約
上級版の要点をまとめます。
- フォント読み込み=カスタムフォントのダウンロード中にブラウザが表示するもの。 フォントは外部リソースであると同時にテキストのメトリクスを変えるため、2つのCore Web Vitalsを同時に悪化させる可能性があります。
- LCP: 最大のテキスト要素を隠すレンダリング阻害フォント(FOIT)はLCPを遅らせます。
auto/block以外のfont-display値ならテキストは表示され、フォント要求がLCPを妨げません。 - CLS: 代替フォントからWebフォントへの切り替えがレイアウトを再配置します。FOITでも、非表示テキストは代替フォントのメトリクスで配置されるためCLSが起こります。
- 主な調整手段は
font-display:swap=FOUT(テキストは速いが切り替わる)。optional=約100ms後に使用フォントを確定するため、その後の切り替えも、それによるシフトもありません。web.devはブランド要素にswap、本文にoptionalという使い分けを提案しています。 - プリロードはフォントの検出遅延を解消します。**プリロード+
font-display: optional**は、Googleがレイアウトのがたつきを解消する組み合わせとして挙げています(Chrome 83以降)。過剰なプリロードは他の読み込みから資源を奪います。 - Lighthouseのfont-display監査合格≠CLSの修正。 切り替えによるシフトには、メトリクスの合う代替フォント、または
size-adjust/ascent-override/descent-override/line-gap-overrideが別途必要です。 - Google Fontsは
&display=URLパラメータでfont-displayを設定でき、セルフホスティングは不要です。ただしセルフホスティングなら追加接続を省けます。 - 直接のランキング要因ではありません。 タイブレーカー的なページエクスペリエンスシグナルであるCLS/LCPに影響します。最善策はシステムフォントです。
公式ドキュメント
GoogleとBingの一次資料です。
- フォントのベストプラクティス (web.dev)—
font-displayの値一覧(ブロック/スワップ期間)と使い分けの助言。 - Cumulative Layout Shiftを最適化する (web.dev)— FOIT/FOUTの説明と、両方がレイアウトシフトを起こす理由。
- Largest Contentful Paintを最適化する (web.dev)— WebフォントがLCPリソースになる場合と、
font-displayがテキストを表示し続ける仕組み。 - optionalフォントのプリロードでレイアウトシフトとFOITを防ぐ (web.dev)— プリロード+
font-display: optionalの組み合わせとChrome 83での修正。 - WebFontの読み込みとレンダリングを最適化する (web.dev)— フォント読み込みパフォーマンスの総合ガイド。
- 学習ガイド:Webフォントを最適化する (web.dev)— 構造化された学習版。
- Webフォント読み込み中もテキストを表示する (Chrome for Developers)— Lighthouseのfont-display監査。Lighthouse 13以降は単独監査から、より広い「Font display insight」パネルへ移動したため、古い画面やガイドでは以前の名称が使われています。
- Google Fonts CSS2 API —
displayパラメータ — セルフホスティングせずURLからfont-displayを設定する方法。 - MDN —
font-display— Google自身の文書が値の定義で参照するCSS仕様リファレンス。
Bing/Microsoft
- Microsoft Bingの高速なフロントエンドパフォーマンス (Bing Search Quality Insights、2022年8月)— Bing自身の検索結果ページで、フォントのプリロードを本番技術として使っていることを説明します。この記事が確認するのはプリロードの仕組みだけで、
font-display、FOIT/FOUT、CLS、LCPには言及していません。
出典からの引用
GoogleのChrome/web.dev文書とBingのエンジニアリング記事にある公式見解です。フォント読み込みはレンダリング/パフォーマンス仕様の領域なので、ここでの一次情報源はChromeとweb.devのチーム(Search Relationsではありません)です。font-displayをランキングの話題とするSearchチームの公式発言はなく、存在しない引用を作ることはしません。
Google — web.dev(Chromeチーム)
- “Both approaches can cause layout shifts. Even if the text is invisible, it’s still laid out using the fallback font, so when the web font loads, the text block and the surrounding content shift” (翻訳) 「どちらの方法もレイアウトシフトを起こす可能性があります。テキストが非表示でも代替フォントで配置されるため、Webフォントが読み込まれるとテキストブロックと周囲のコンテンツが移動します。」 — web.dev、Optimize Cumulative Layout Shift。 引用箇所へ移動
- “The fallback font is swapped with the web font, incurring a Flash of Unstyled Text (FOUT). ‘Invisible’ text is displayed using the fallback font until a web font is available and the text is made visible (FOIT—flash of invisible text).” (翻訳) 「代替フォントがWebフォントに置き換わることでFlash of Unstyled Text(FOUT)が発生します。Webフォントが利用可能になりテキストが表示されるまで、『非表示』のテキストは代替フォントで表示されます(FOIT、flash of invisible text)。」 — web.dev、Optimize Cumulative Layout Shift。 引用箇所へ移動
- “If you set a
font-displayvalue of anything other thanautoorblock, then text will always be visible during load, and LCP won’t be blocked on an additional network request.” (翻訳) 「font-displayにautoまたはblock以外の値を設定すると、読み込み中もテキストは常に表示され、追加のネットワーク要求によってLCPが妨げられることはありません。」 — web.dev、Optimize Largest Contentful Paint。 引用箇所へ移動
Bing — 本番環境でのフォントのプリロード
- Bingのエンジニアリングチームは、
<head>内のプリロードタグがカスタムWebフォントのダウンロードをすぐ始めるようブラウザへ指示すると説明しています。このタグがなければ、ブラウザはCSSを解析して一致する要素に出会うまでフォントを取得しません。プリロードによってテキストの描画に間に合うようフォントを利用できます。 記事を読む
#:~:text=のディープリンクは、公開ページの引用箇所へ直接移動します。
フォント読み込みチェックリスト
フォントが気づかないうちにCore Web Vitalsを悪化させていないか、手早く確認します。
- すべてのカスタム
@font-face(またはGoogle Fonts URL)で、ブラウザのデフォルトではなく、意図したfont-display値を設定している。 - 本文で
font-display: optional(またはメトリクスを合わせたswap)を使い、切り替えによるレイアウトシフトを避けている。 - ファーストビューで使う1〜2個のフォントを
<link rel="preload" as="font" type="font/woff2" crossorigin>でプリロードしている。 - すべてのウェイトではなく、初期描画に必要なものだけをプリロードしている。
- プリロードの
href、as="font"、type、crossoriginが実際の@font-face要求と一致することをNetworkパネルで確認し、未使用プリロードや重複ダウンロードがない。 -
font-familyスタックにはカスタムフォントだけでなく、妥当なシステム代替フォントがある。 - 切り替えでまだ動く場合は、代替フォントのメトリクスを
size-adjust、ascent-override、descent-override、line-gap-overrideで合わせている。 - フォントをWOFF2で配信し、実際に使う文字/ウェイトへサブセット化している。
- Google Fontsの埋め込みに
displayパラメータとfonts.gstatic.comへのpreconnectがある。 - 複数バリエーションを描画するときだけ可変フォントを使い、それ以外では軽い可能性のある単一の静的ウェイトも検討している。
- PageSpeed Insights/Lighthouseで、フォントがLCP要素やCLSの原因でないことを確認した。
判断の枠組み
1. フォントは2つの仕組みで2つの指標に影響する。
LCPでは、レンダリング阻害フォントが読み込みまで最大のテキスト要素を隠します。CLSでは、代替フォント→Webフォントの切り替えがテキストのメトリクスを変えて再配置します。swapはLCPに役立ってもCLSを直さないため、別々の問題として対処します。
2. FOIT対FOUT — 失敗の仕方が違う。 FOIT(読み込みまで非表示)は描画遅延→LCPの危険があります。FOUT(代替フォント後に切り替え)はレイアウトシフト→CLSの危険があります。「安全なデフォルト」はなく、選択して問題を緩和する必要があります。
3. font-displayの判断。
optional=約100msの時間枠後に使用フォントを確定し、その後は切り替えない(CLSに敏感な本文向け)。swap=テキストをすぐ表示し、最終的にブランドフォントを必ず使う(ブランド要素向けで、小さなシフトを許容)。どこでも同じ値にせず、要素ごとに使い分けます。
4. 検出と描画を分ける。
プリロードは検出(ブラウザがフォントを早く知る)を直します。font-displayは描画挙動(読み込み中に何を表示するか)を直します。代替フォントのメトリクス調整はシフト自体を直します。3つは別の調整手段で、すべて必要になることも少なくありません。
5. 良い/より良い/最善の順序。
良い: フォントをプリロードする(同一オリジンなら追加接続も省けます)。より良い: プリロードとfont-display: optionalを組み合わせ、遅いフォントならデフォルトを表示して次回用にキャッシュする。最善: システムフォントを使う。読み込みがないので遅延もシフトもありません。
フォント読み込み早見表
font-displayの値(web.devによるブロック/スワップ期間):
| 値 | ブロック | スワップ | 適する用途 |
|---|---|---|---|
auto | ブラウザ依存 | ブラウザ依存 | 特になし — 管理されていないデフォルト |
block | 2〜3s | 無限 | まれ — FOITを起こしLCPを悪化させる可能性がある |
swap | 0ms | 無限 | ブランド/見出し(テキストは速いが、切り替えで動く可能性がある) |
fallback | 100ms | 3s | 短いブロックと限定的なスワップ期間の折衷案 |
optional | 100ms | なし | 本文(切り替えがなく、それによるCLSもない) |
上の数値はweb.devが文書化したChromiumの挙動です。CSS仕様自体はブロック/スワップの期間分類(short、extremely small、infinite、none)だけを定義し、正確な時間はブラウザに委ねています。テスト対象ブラウザの現行値を確認してください。
2つの失敗モード
- FOIT=読み込みまで非表示→LCP遅延の危険。
- FOUT=代替フォント後に切り替え→レイアウトシフト→CLSの危険。
- 切り替えが起こればどちらもCLSを生じます。防げるのは代替フォントのメトリクス調整または
optionalです。
優先順位順の対策
- システムフォントを使う(読み込みなし)。
- 重要なフォントをプリロードする(
as="font" type="font/woff2" crossorigin)。 font-displayを設定する(本文はoptional、ブランドはswap)。- 代替フォントのメトリクスを合わせる(
size-adjust、ascent-override、descent-override、line-gap-override)。 - サブセット化+WOFF2でファイル自体を小さくする。
Google Fontsの要点
- CSS2 URLに
&display=swap(またはoptional/fallback)を追加し、セルフホスティングせずfont-displayを設定できます。 - それでもレンダリングを妨げるスタイルシート+別のフォント要求です。
fonts.gstatic.comへpreconnectを追加します。 - セルフホスティングなら追加のDNS/接続を省けます。
診断
- PageSpeed Insights/Lighthouseの「Font display insight」(Lighthouse 13より前は単独の「Ensure text remains visible during webfont load」監査)。
- Chrome DevToolsのPerformance/Networkパネルで、初回描画やシフトとの相対的なフォント読み込み時刻を確認します。
フォント読み込みの誤解と失敗
どれも監査でよく見つかる実際の問題です。誤りの理由と代わりにすべきことを示します。
「font-display: swapでCLS問題は完全に解決する」
誤りの理由: swapはFOITを解消し、テキストをすぐ表示するためLCPやLighthouse監査には有効ですが、FOUTを必ず起こします。代替フォントとWebフォントの大きさが違えば、切り替えによるシフトは残ります。GoogleのLighthouse文書も、切り替えが起きた後のCLSへの影響はFOITとFOUTで同じだとしています。
代わりに: メトリクスを合わせた代替フォントと組み合わせる(またはoptionalを使う)ことで、切り替え時に何も動かないようにします。
「フォントをプリロードすればページは必ず速くなる」 誤りの理由: web.devは、プリロードが他のリソース読み込みに使うブラウザ資源を奪う代償を伴うと明記しています。ファーストビューに不要なフォントをプリロードすると、より重要な処理が遅れます。 代わりに: 初期描画に必要な1〜2個だけをプリロードします。
「font-display: optionalではカスタムフォントが読み込まれない」
誤りの理由: フォントは読み込まれ、キャッシュされます。約100msの時間枠に間に合わなかったそのページ読み込みで使われないだけです。キャッシュ後のページ表示では通常すぐ使われます。
代わりに: 再訪問者がブランドフォントを見られないと心配せず、CLSに敏感な本文でoptionalを使います。
「font-displayを何か設定してLighthouseの『非表示テキスト』警告が消えたから完了」
誤りの理由: 監査合格は必要でも十分ではありません。切り替えによるレイアウトシフトは、関連する別の問題です。
代わりに: 監査を解消した後にCLSを確認し、まだ動くなら代替フォントのメトリクスを直します。
「Google Fontsは自動最適化され、CWV問題を起こさない」
誤りの理由: コピーしたGoogle Fonts埋め込みも、displayとpreconnect/preloadを設定しなければ、レンダリングを妨げるスタイルシート要求と別のフォント要求です。「Google製だから大丈夫」は現場の監査でよくある見落としです。
代わりに: &display=とfonts.gstatic.comへのpreconnectを追加し、重要なウェイトをプリロードします。
「フォント読み込みはUXだけの問題でSEOには関係ない」 誤りの理由: CLSとLCPはCore Web Vitalsであり、Googleのページエクスペリエンスシグナルの一部です。フォントの選択はテクニカルSEOの対象です。 代わりに: フォント読み込みをCWV施策として扱いつつ、重要度の比率は正しく保ちます(ページエクスペリエンスはタイブレーカーで、主要因ではありません)。
ページで読み込まれるフォントを探す
ブラウザが実際に読み込んだすべてのフォントフェイスと完了状態を一覧にする、DevTools Console用の短いスニペットです。重いフォントや遅いフォントの発見に役立ちます。
Chrome DevTools Console
// List loaded font faces and their status
[...document.fonts].map(f => ({
family: f.family,
weight: f.weight,
style: f.style,
status: f.status, // "loaded", "loading", "unloaded", "error"
display: f.display, // the font-display value in effect
}));
// When did fonts finish loading? (relative to navigation start)
document.fonts.ready.then(() =>
console.log("All fonts ready at", performance.now().toFixed(0), "ms")
);フォントによるレイアウトシフトを監視する
Consoleへ貼り付けると、移動した要素を含むCLSエントリを発生時に記録します。フォント切り替えが原因かを確認するのに便利です。
Chrome DevTools Console
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
console.log("Layout shift", entry.value.toFixed(4),
entry.sources?.map(s => s.node));
}
}
}).observe({ type: "layout-shift", buffered: true });フォントファイルがWOFF2で適切なサイズか確認する
フォントはWOFF2で配信し、サブセット化すべきです。次のコマンドにフォントURLを指定してサイズと種類を確認します。
macOS/Linux
curl -sI https://example.com/fonts/brand.woff2 \
| grep -iE "content-type|content-length"Windows/PowerShell
$r = Invoke-WebRequest -Method Head https://example.com/fonts/brand.woff2
$r.Headers["Content-Type"]; $r.Headers["Content-Length"]単一ウェイトのcontent-lengthが数百KBに達するほど大きい場合は、サブセット化/圧縮の余地があります。
ページに合うフォント読み込み戦略はどれか
重要な本文フォントはどのように読み込むべきですか?
フォント読み込みの変更が機能したことを証明する
重要フォントのプリロードテスト
実行するテスト: キャッシュを無効にして再読み込みし、Networkパネルでフォント要求のイニシエーターと開始時刻を調べる。期待結果: 対象の重要フォントが早期に開始され、重複ダウンロードなしにCSSから再利用される。失敗の解釈: プリロード属性がCSS要求と一致しない、またはそのフォントは実際には重要でない。監視期間: 即時。ロールバック条件: 重複要求、Consoleエラー、またはより重要なリソースを遅らせる競合。
フォント切り替え安定性テスト
実行するテスト: 読み込みをスロットリングしながらPerformanceパネルのLayout Shiftsトラックを記録する。期待結果: 代替フォントのテキストが表示され続け、最終フォントでも計測可能なシフトが起きない。失敗の解釈: 代替フォントのメトリクスがまだ異なる、または切り替えが遅すぎる。監視期間: 対応する各ブレークポイントで即時。ロールバック条件: テキストの非表示、切れ、またはCLSの悪化。
フィールド指標テスト
実行するテスト: 変更テンプレートのリリース後LCP/CLSを以前のRUMベースラインと比較する。期待結果: 他方を悪化させず対象指標が改善する。失敗の解釈: フォントがボトルネックではなかった、または読み込み速度と不安定さを交換してしまった。監視期間: トラフィック到着に応じたRUM、およびローリング期間のCrUX。ロールバック条件: いずれかのフィールド指標が一貫して悪化する。
参考になるリソース
私の関連記事
- Cumulative Layout Shift(CLS)とは何か、改善する方法 (Ahrefs)— フォント起因のシフトに対するプリロード+
font-display: optionalの修正を含むCLSガイド。 - Largest Contentful Paint(LCP)とは何か、改善する方法 (Ahrefs)— LCPにおけるフォント対策の良い/より良い/最善の順序。
- Core Web Vitals(CWV)とは何か、改善する方法 (Ahrefs)— CLSとLCPがCWV全体で占める位置。
- Patrick Stox on the Ahrefs blog — その他のテクニカルSEO記事。
業界の参考資料
- Webフォントによるレイアウトシフトを修正する (DebugBear、Umar Hansa)— 計測→フォント特定→
font-display→より良い代替→メトリクス調整までを通した解説。 - Webフォント読み込み中もテキストを表示する (DebugBear)— Lighthouse監査に特化したトラブルシューティング。
- Webフォントによるレイアウトシフトを避ける方法 (Simon Hearne)— 実務者向けの詳細解説。
- FOUT, FOIT, FOFT (CSS-Tricks)— 用語の定番解説。
- CSSフォント記述子でフォント読み込みの影響を減らす新しい方法 (Smashing Magazine)—
size-adjust/ascent-override/descent-override/line-gap-overrideの詳細。 - Webフォント使用時のレイアウト再フローを減らす方法 (Material Design)— GoogleのMaterialチームによるCSS記述子の実践的な解説。
- Google Fontsにfont-displayを導入した (Addy Osmani)—
displayURLパラメータと、font-display制御のためのセルフホスティングが不要になった理由。
理解度チェック:フォントの読み込み
WebフォントがCore Web Vitalsへ与える影響についての5問です。各問で回答を選び、答えを確認してください。
変更履歴
2026年9月7日に更新。
編集概要と記録された変更の詳細。概要
本文とメタデータに残っていた英語と仮訳接頭辞を解消し、現行英語ソースに忠実な自然な日本語へ全面改稿。引用原文は保持し、日本語訳を併記。
変更の詳細
-
全レンズの見出し、本文、一覧、表を自然な日本語に翻訳し、コード、URL、製品名、数値、証拠境界は維持。DecisionTreeとQuizの保護プロパティは英語ソースのまま保持し、既存の49フィールドの日本語コンポーネントサイドカーを再検証。
-
web.devの英語引用を原文のまま保持し、各引用に明示した日本語訳を追加。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年9月3日に更新。
編集概要と記録された変更の詳細。概要
監査で検出された2つのfont-display表に残っていた英語の見出しと説明を日本語化。
変更の詳細
-
AdvancedとCheat Sheetsのfont-display表について、値、期間、用途の説明を翻訳し、コード値と数値はそのまま維持。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年7月17日に更新。
編集概要と記録された変更の詳細。概要
font-displayの時間表について、正確なms/秒の値はChromiumで文書化された挙動であり、ブラウザ横断の仕様保証ではないことを明記。さらに、検出/CORS/キャッシュ状態のパイプライン、プリロード要求の一致条件、メトリクス上書きの対応状況に関する注意、Google Fontsとセルフホスティングおよびサブセット化の判断要因を追加。
変更の詳細
-
font-displayのブロック/スワップ期間表に注意書きを追加。CSS仕様が定義するのは期間の分類(short、extremely small、infinite、none)のみであり、ミリ秒・秒の値はweb.devが文書化したChromiumの挙動で、ブラウザ横断の保証ではない。
-
「フォントが特殊な理由」に宣言/マッチング、CORSが関与する取得、キャッシュ状態の違いを説明するパイプラインを追加。プリロード節とチェックリストには、href/as/type/crossoriginが実際の@font-face要求と一致する必要があることを追加。
-
Google Fonts対セルフホスティング、可変フォント、サブセット化を、普遍的な優劣や削減率ではなく、文字体系/ウェイト/ライセンス/キャッシュに基づく判断として整理。4つのメトリクス上書き記述子にはブラウザ対応状況の注意を追加。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。