Webフォント導入時の読み込み速度問題|ブロッキングを避けるための実装テクニック

C
クリオ
Web制作ディレクター / フロントエンジニア

こんにちは!

今日は「Webフォント導入時の読み込み速度問題」について、実践的な解決方法をお話しします。

Webフォントのブロッキング問題とは

僕も実際に経験したんですけど、Webフォントって便利な反面、めっちゃやっかいな問題を引き起こすんですよ。
特に「読み込み完了までテキストが表示されない」という現象。
これをFOIT(Flash Of Invisible Text)と呼びます。

現場で見るあるあるなんですが、デザイナーさんが「このフォント、素敵やん」って選んで、いざ実装したら、ユーザーが訪問した直後の3秒間、ページがテキスト表示なしの真っ白な状態になる…みたいなことが起きるんですよ。
スマホユーザーなんか通信が遅いから、もっと長くなる。
これって、ユーザー体験としては最悪ですよね。

実は、ブラウザの初期動作がこの原因なんです。
ブラウザは、デフォルトではWebフォントのダウンロードが完了するまで、そのフォントを使うテキストを表示しないように設計されています。
3秒待ってもフォントが来なければ、フォールバックフォント(通常はシステムフォント)で表示する仕様になってるんですが、その待機時間がめっちゃ長く感じられる。

font-displayプロパティで読み込み動作を制御する

ここで活躍するのが、font-displayというCSSプロパティです。
これを使うことで、Webフォント読み込み中の表示動作を自分たちでコントロールできるんですよ。

主な値は5つあります。

  • auto:ブラウザのデフォルト動作(通常はFOIT)
  • block:フォント完了まで最大3秒待機。超過時にフォールバック表示
  • swap:フォント完了まで最大3秒待機。待機中はフォールバック表示
  • fallback:最初からフォールバック表示。100msだけフォント待機
  • optional:最初からフォールバック表示。フォント到着時に切り替え

僕が現場で一番よく使うのは、正直なところswapです。
ほんまに、これが一番バランスが取れてるんですよ。

実装例を見てみましょう。

@font-face {
  font-family: 'MyCustomFont';
  src: url('/fonts/my-font.woff2') format('woff2');
  font-display: swap;
}

このfont-display: swapを設定すると、何が起きるかというと:
ページ訪問直後、システムフォント(ブラウザのデフォルトフォント)で即座にテキストが表示される。
その後、バックグラウンドでWebフォントのダウンロードが進み、完了したら自動的にそのフォントに切り替わる、という流れになります。

ユーザー体験としては、「あ、フォント変わったな」って一瞬気付くかもしれませんが、3秒以上待つよりは遥かにマシなんですよ。

実装の工夫とベストプラクティス

ただ、font-display: swapだけでは不十分な場合があります。
複数のWebフォントを読み込む場合、さらに工夫が必要なんです。

まず、フォント自体の最適化をする必要があります。
WOFF2形式で配信する、不要なウェイトを削減する、といったことですね。

@font-face {
  font-family: 'MyCustomFont';
  src: url('/fonts/my-font-regular.woff2') format('woff2'),
       url('/fonts/my-font-regular.woff') format('woff');
  font-display: swap;
  font-weight: 400;
}

@font-face {
  font-family: 'MyCustomFont';
  src: url('/fonts/my-font-bold.woff2') format('woff2'),
       url('/fonts/my-font-bold.woff') format('woff');
  font-display: swap;
  font-weight: 700;
}

重要なポイントは、ウェイトごとに別ファイルにして、font-weightを明確に指定することです。
こうすることで、ブラウザは必要なウェイトだけをダウンロードするようになる。
ぼくも最初はこれに気付かず、全ウェイトが一つのファイルに入ってて、めっちゃファイルサイズが大きくなってたんですよ。

次に、優先度を考えるのも大事です。
見出しにしか使わないWebフォントと、本文に使うWebフォントでは、読み込み優先度が違う。
本文フォントを優先的に読み込ませるようにするといいですよ。

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

本文フォントにrel="preload"を付けることで、ブラウザに「これ早めに読み込んでね」というヒントが与えられます。

あ、そして関西弁で言わせてもらうと「可変フォント」を使うのも、ほんまにめっちゃ有効な選択肢ですよ。
可変フォント(Variable Font)なら、複数のウェイトを1つのファイルで管理できるから、ファイル数が減って、結果的に読み込み速度が向上することもあります。

ただし、ブラウザサポートを確認する必要があります。
今のご時世ではほぼ問題ないんですが、念のため確認しとくといいですよ。

まとめ

Webフォントの読み込み速度問題は、多くのWeb制作者が経験する悩みです。
でも、font-display: swapを活用して、フォントファイルを最適化し、優先度をつけることで、かなり改善できるんです。

ここまでのポイントをまとめるなら:

  • font-display: swapを使って、フォント完了待機中もテキスト表示する
  • ウェイトごとに別ファイルにして、ファイルサイズを削減する
  • 本文フォントにrel="preload"を付けて優先度を上げる
  • 可変フォント導入も検討する

僕の経験から言うと、これらを組み合わせるだけで、PageSpeed Insightsのスコアがかなり改善されることが