font-display swapとは?Webフォントのずれ対策

font-display swapを解説。block、fallback、optionalとの違い、プリロードとsize-adjustでずれを防ぐ方法。

目次

font-display swap(font-display: swap)は、ブラウザーにまずフォールバックフォントでテキストをすぐ表示させ、Webフォントが届いたら差し替えるよう指示します。見えないテキストで待たされる時間はなくなりますが、レイアウトシフトはなくなりません。Webフォントがフォールバックより幅や高さが大きいと、差し替えの時にテキストが組み直されます。テキストを速く表示しつつレイアウトを安定させるには、swapを設定し、フォントを早く読み込み、size-adjustでフォールバックフォントのサイズをWebフォントに合わせます。以下では、font-displayの5つの値を比べ、各手順のコードを示します。

font-display swapの働き

swapは、フォントフェイスに「極めて短いブロック期間と無限の交換期間」を与えます(MDN、2026年9月10日最終更新)。簡単に言うと、テキストが長時間隠されることはなく、Webフォントは読み込みが終わった時点で、たとえ1分後でも使われます。

MDNはこの2つの期間を次のように定義しています。ブロック期間には、まだ読み込まれていないフォントを使う要素は、見えないフォールバックフォントで描画しなければなりません。交換期間には、見えるフォールバックフォントで描画し、間に合って読み込まれたフォントは通常どおり使われます。よく使われる呼び名は、FOIT(flash of invisible text、ブロック期間)とFOUT(flash of unstyled text、交換)です。

font-displayを指定しないと、ブラウザーが判断します。web.devのフォントガイド(2022年10月)によると、Chromium系ブラウザーとFirefoxは、フォントが読み込まれないと最大3秒間テキストの描画をブロックし、Safariは無期限にブロックします(web.dev)。これはそれらのバージョンの振る舞いとして捉え、対象とするブラウザーを確認してください。

font-displayは、2020年1月から新たにBaselineで利用可能になり、2022年7月から広く利用可能です。web-featuresでは、Chrome 60、Firefox 58、Safari 11.1、Safari iOS 11.3から掲載されています(web-features 3.44.0、2026年10月22日)。

@font-face {
  font-family: "Brand";
  src: url("/fonts/brand.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

font-displayの値の比較

5つの値の違いは、テキストが見えないままでいる時間と、遅れて届いたフォントを差し替えられる時間だけです。web.devの表による期間は次のとおりです。

値 ブロック期間 交換期間 使いどころ
auto ブラウザーが決める ブラウザーが決める 明示的な選択をしない(既定)
block 2〜3秒 無限 まれに使う。フォントの読み込み中はテキストを隠す
swap 0 ms 無限 Webフォントを使うべき見出しとブランドのテキスト
fallback 100 ms 3秒 折衷案。ブロック期間が非常に短く、交換期間も短い
optional 100 ms なし 本文。正確なフォントよりレイアウトの安定が重要な場合
font-displayの各値のブロック期間とスワップ期間:autoはブラウザ任せ、blockは文字を2〜3秒隠し、swapはブロックなし、fallbackは100ms隠して3秒間スワップ可、optionalは100ms隠してスワップなし

web.devは、フォントが十分早く届いてレイアウトシフトが起きないのであれば、テキストを速く表示してWebフォントで描画したい場合にswapを推奨しています。最もパフォーマンスが高いのはoptionalで、代償として、フォントの到着が遅れるとWebフォントは使われません。web.devは、ブランドや特徴的な要素にはswap、本文にはoptionalを勧めています(web.dev)。この使い分けは推奨であり、仕様が求めているものではありません。

Lighthouseもこれを確認します。Lighthouseの「Font display」のインサイト(2025年10月)は、テキストを見えたままにするためにfont-displayをswapかoptionalに設定するよう求めます。swapの場合は、レイアウトシフトを減らすためのフォントのメトリクスの上書きを案内しています(Chrome for Developers)。

重要なフォントをプリロードする

プリロードはフォントのダウンロードを早く始めるので、フォールバックフォントで過ごす時間が短くなります。自前でホストするフォントのプリロードには、as="font"、MIMEタイプ、crossoriginが必要です。

<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>

MDNは、フォントのプリロードにはcrossoriginが必須で、クロスオリジンでなくても、リクエストのCORSモードと一致させる必要があると述べています。フォントはCORSの匿名モードで取得されるためです(MDN、2026年5月)。

プリロードは、最初の画面に必要なものだけにしてください。web.devは、プリロードはunicode-rangeの宣言を無視するため、使う場合は1つのフォント形式だけを読み込むよう注意しています。すぐに必要でないフォントには使わないでください。プリロードは、2021年1月から新たにBaselineで利用可能になり、2023年7月から広く利用可能です(web-features 3.44.0)。

Google Fontsかセルフホストか

Google Fontsでは、スタイルシートのURLにdisplayパラメーターを追加し、両方のフォントのオリジンに早めに接続します。

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Crimson+Pro&display=swap" rel="stylesheet">

displayパラメーターは、同じ5つの値を取ります。Googleのドキュメントは、既定値がautoであり、別の値のほうが適していることが多いと説明しています(Google Fonts、2024年7月更新)。フォントファイルのpreconnectにはcrossoriginが必要です。「スタイルシートと違い、フォントファイルはCORS接続で送られなければならない」からです(web.dev)。

Google Fontsとセルフホストのどちらが速いかについて、web.devは、差は見た目ほど明確ではないと述べています。引用されたWeb Almanacのデータでは、サードパーティのフォントは自社のフォントより速く描画されました。一方、セルフホストは、CDNとHTTP/2を使うと有利になりやすいとしています。セルフホストする場合は、最適化の責任もあなたにあります。WOFF2を配信し(web.devによると、WOFFより30%圧縮効率が高い)、unicode-rangeでサブセット化し、まずフォントのライセンスを確認してください。

フォールバックフォントでレイアウトシフトを防ぐ

差し替えの時にずれるのは、フォールバックフォントとWebフォントのメトリクスが違うからです。対策は、フォールバックを合わせて調整することです。web.devのCLSのガイドは、「初期のフォールバックより大きく、または小さく描画されるフォント」をレイアウトシフトの原因に挙げており、CLSの良好な値は0.1以下です(web.dev、2023年4月)。すべての原因については、cumulative layout shiftのガイドを参照してください。

幅の狭い代替フォントでは2行だった見出しが、幅の広いWebフォントに切り替わると3行になり、下のボタンが押し下げられる。これがレイアウトシフト

手段は、ローカルのフォントを指す2つ目の@font-faceを作り、それを拡大縮小することです。size-adjustは、グリフの輪郭とメトリクスを割合で拡大縮小します。ascent-override、descent-override、line-gap-overrideは行ボックスを設定します。

@font-face {
  font-family: "Poppins fallback";
  src: local("Arial");
  size-adjust: 60.85%;
}

body {
  font-family: "Poppins", "Poppins fallback", sans-serif;
}

60.85%は、Poppins と Arial という1組のフォントについてのものなので、自分のフォントの値は計算が必要です。Chromeの記事によると、size-adjustはWebフォントの平均文字幅をフォールバックフォントの平均文字幅で割った値です(この例では538.01 / 884.14 = 60.85%)。多くの場合は近似することしかできません。3つの上書きの記述子は、Webフォントのascent、descent、line gapを、em単位とsize-adjustの値で割って計算します。記事(2023年2月更新)が挙げるツールで、フォントごとに計算してください。Fontaine、Capsize、next/font(Next 13以降)、@nuxtjs/fontaineがあります(Chrome for Developers)。頼る前に、ブラウザーで結果を確認してください。

記述子ごとの対応は、MDN browser-compat-data 8.1.7(2026年10月)によると次のとおりです。

記述子 Chrome Firefox Safari
size-adjust 92 92 17
ascent-override、descent-override、line-gap-override 87 89 非対応

web-featuresは3つの上書きをBaselineとして載せていないため、iPhoneのSafariはそれらを無視し、わずかにずれることがあります。フォールバックフォントも端末によって変わります。Chromeの記事は、AndroidのRobotoフォールバックでは、Arialとは異なる値が必要だと述べています。

スマートフォンのLCPテキストへの影響

Webフォントは、いちばん大きな要素がテキストの場合、Largest Contentful Paintを遅らせることがあります。web.devのLCPのガイドは、テキストはブロック期間が終わるまで描画されたとみなされないと説明しています。そのため、Webフォントのテキストが表示されるまでは、より小さい要素がLCPとして報告されることがあります。LCPの候補には、<p>や<h1>などのブロックレベルのテキスト要素も含まれます。良好なLCPは2.5秒以下です(web.dev、2025年9月)。

LCPがWebフォントの見出しであるページでは、遅い携帯回線で、フォントのダウンロードが他のすべてと競合します。そのため、swapやプリロードの手間をかける価値があります。LCP要素の読み方はLighthouseでのモバイル監査ガイドに、LCPが遅い他の原因はモバイルページ速度テストのガイドにあります。

スマートフォン幅のページで結果を確認する

変更後は、コールドロードでページを見てください。スマートフォンの幅でキャッシュを無効にして再読み込みし、フォントが届いたときに見出しが跳ねるかどうかを確認します。Mobile View Extensionは、タブをスマートフォンのユーザーエージェント、画面サイズ、ピクセル比で読み込み直します。そのため、モバイルのレイアウトと、どのフォールバックフォントが表示されるかを確認できます。ただし、読み込み時間、レイアウトシフト、速度の指標は測定できず、デスクトップのフォントと回線を使うので、スマートフォンのフォールバックフォントは違って見えることがあります。Lighthouseとフィールドデータで測定してください。

よくある質問

font-display swapは何をしますか?

テキストをフォールバックフォントですぐに表示し、フォントが読み込まれたらWebフォントに差し替えます。その差し替えがいつ起きても制限はありません。ブロック期間は極めて短く、交換期間は無限です(MDN)。

swapとoptionalのどちらがよいですか?

どこでも優れているものはありません。swapは必ずWebフォントで終わりますが、レイアウトをずらすことがあります。optionalはずれを防げますが、読み込みが遅い場合はWebフォントを飛ばすことがあります。web.devは、ブランドにはswap、本文にはoptionalを勧めています。

font-display swapはレイアウトシフトの原因になりますか?

なることがあります。フォールバックとWebフォントのメトリクスが違うと、差し替えでテキストのサイズと行の高さが変わり、コンテンツが動くことがあります。web.devは、これをレイアウトシフトの原因の1つに挙げています。size-adjustでフォールバックを合わせると、その影響を減らせます。

Webフォントはプリロードすべきですか?

最初の画面に必要な1〜2個のフォントを、as="font"とcrossoriginを付けてプリロードしてください。web.devは、プリロードはunicode-rangeを無視するので、控えめに使うよう勧めています。

次のサイトをモバイル表示で確認しましょう。

拡張機能を追加して、作業中のタブのまま端末プレビューを開けます。