連載「実例に学ぶサイトスピード改善」
実在サイトの表示速度ボトルネックを取り上げるシリーズ。原因と対処法をシミュレーションの数値で示しながら解説する。事例の詳細は弊社の表示速度ボトルネック実例研究(vigilante)で公開している。
- LCP画像は最優先で読み込ませる
- 画像は次世代フォーマットに移行する
- テキストはGZIP/Brotliで圧縮する
- 重い日本語Webフォントが表示を遅らせる(本記事)
- 外部CDNは速いとは限らない
- 画像の寸法指定でガクッと動くページを防ぐ(近日公開)
- head内の同期スクリプトが描画を止める(近日公開)
日本語Webフォントは英語フォントと事情が違う
Webフォントはデザインの道具という認識が強く、パフォーマンス改善の議論では画像やJavaScriptに比べて後回しになりやすい。しかし日本語Webフォントは、英語フォントとは事情が大きく異なる。
日本語は文字種が多く、ひらがな・カタカナ・漢字を合わせると、フォントファイルが数MB単位になることがある。この転送コストがFCPやLCPのレンダリングをブロックし、ページの初期表示を遅らせる原因になりうる。
弊社の表示速度ボトルネック実例研究(vigilante)では、日本語Webフォントが主要なボトルネックとして観測されたサイトを複数記録している。問題のパターンは一様でない。6MB超のフォントが転送を圧迫するケース、レンダリングブロックでFCPとLCPが大きく遅れるケース、実際には使われていないフォントが読み込まれているケースなど、性質がそれぞれ違う。
この記事では4つの実例を取り上げ、日本語Webフォントがサイトスピードに与えている影響をシミュレーションの数値とともに解説する。
日本語フォントはなぜ重くなるのか
理由は単純だ。数百字で足りる英語フォントに対し、日本語は漢字まで含めて数千から数万字を抱える。その差がそのままファイルサイズに表れる。
Noto Sans JPのような一般的な日本語フォントは、フルセットなら1ウェイトでも1.5〜2MB、複数ウェイトで数MBに達する。アイコンフォントとして全文字セットを読み込めば、さらに重くなることもある。
さらにブラウザは、Webフォントの到着を待って該当部分の描画を止めることがある(FOIT:Flash of Invisible Text)。font-display 未設定だとこの挙動が起きやすく、FCPやLCPの遅延につながる。

※woff2・フルセットの目安。日本語はサブセット化で数百KBまで削減できる。
実例で確認する日本語Webフォントの影響
弊社の表示速度ボトルネック実例研究(vigilante)では、ボトルネックを一つずつ切り分けてシミュレーションし、before/afterの数値を記録している。以下の4サイトでは、日本語Webフォントが観測されたボトルネックのひとつだった。
e☆イヤホン: Noto Sans Japanese 6.05MBの転送コスト
国内最大級のイヤホン・ヘッドホン専門店e☆イヤホンのトップページでは、Noto Sans Japaneseの3ウェイト(Regular / Semi-Bold / Bold)が読み込まれており、フォントファイルの合計サイズは6.05MBに達していた。
日本語Webフォントは文字種の多さからデータ量が非常に大きくなる。このシミュレーションでは @font-face 定義を削除し、CSSのフォント指定をシステムフォントスタック(-apple-system、BlinkMacSystemFont、Hiragino Kaku Gothic ProN など)にフォールバックする変更を加えた。サイトの見た目がシステムフォントに変わることを前提としたシミュレーションだ。
| 指標 | 解消前 | 解消後(シミュレーション) | 変化量 |
|---|---|---|---|
SI | 3.3秒 | 1.7秒 | -1.6秒(48%) |
総合スコア | 99 | 100 | +1 |
シミュレーションの結果、LCP 自体に変化はなかったが、SI(Speed Index = ビューが視覚的に表示される速さ)は3.3秒から1.7秒へと大幅に短縮された。ページ全体の総転送サイズは14.0MBから8.0MBへと43%削減され、フォント転送サイズだけで6.05MBから62.1KBへと99%の削減となっている。
LCP要素が画像だったため、フォント削除がLCPの数値を動かさなかったのは自然な結果だ。とはいえ転送サイズへの影響とSIの改善数値から、日本語Webフォントがページ全体の読み込み体感に与えていた影響の大きさは読み取れる。
詳細はe☆イヤホンのボトルネック研究にまとめている。
ルタオ: 933msのレンダリングブロックとFCP・LCPへの影響
北海道・小樽の洋菓子舗ルタオ(LeTAO)の公式オンラインショップでは、Google FontsからNoto Serif JPを読み込んでいた。このフォントに関連するリソースが描画プロセスの主要なボトルネックとして機能していた状況が観察されている。
| 観察項目 | 詳細 |
|---|---|
| レンダリングブロック | Google Fonts CSSにより933ms相当の描画遅延 |
| 未使用CSS | Google Fonts CSS 150KBが未使用扱い |
| フォントファイル | 14個のwoff2ファイル(約400KB)の転送コスト |
| 外部ドメイン接続 | fonts.googleapis.com / fonts.gstatic.com へのDNS/TLS接続コスト |
シミュレーションではGoogle Fonts(Noto Serif JP)の読み込みを除去し、CSSの font-family をシステムフォント(serif)に置き換えた。フォントの見た目が変わることを前提としたシミュレーションだ。
| 指標 | 解消前 | 解消後(シミュレーション) | 変化量 |
|---|---|---|---|
LCP | 2.8秒 | 0.2秒 | -2.6秒(93%) |
FCP | 1.4秒 | 0.2秒 | -1.2秒(86%) |
SI | 2.2秒 | 1.2秒 | -0.9秒 |
総合スコア | 92 | 97 | +5 |
シミュレーションではLCPが2.8秒から0.2秒へと93%短縮された。この数値は、Noto Serif JPのレンダリングブロックとフォントファイルの転送コストがLCP全体の大部分を押し上げていたことを示している。FCPも1.4秒から0.2秒へと86%改善されており、フォントの読み込みが描画開始そのものを遅らせていたことが読み取れる。
詳細はルタオのボトルネック研究にまとめている。
ロコンド: アイコンフォントとして全文字セット3.88MBを読み込む
靴・ファッションの通販サイトロコンドでは、Google FontsからMaterial Symbols Outlined(3.88MB)とLato(欧文フォント、3ウェイト、42KB)が読み込まれていた。日本語フォントではなく、アイコン用途のフォントが問題だった。
アイコンフォントは文字コードにアイコン画像を対応付ける仕組みだ。使うアイコンが数十種類でも、全文字セットのフォントファイルをそのまま配信する構成になっていると、フォントトラフィックが数MBに達する。実際に使うアイコンはほんの一部でも、ファイル全体がダウンロードされる点に問題がある。
シミュレーションではGoogle Fonts関連の link 要素をすべて削除し、フォントの読み込みを停止した状態を計測した。
| 指標 | 解消前 | 解消後(シミュレーション) | 変化量 |
|---|---|---|---|
LCP | 1.8秒 | 1.1秒 | -0.7秒 |
FCP | 1.6秒 | 1.0秒 | -0.6秒 |
SI | 1.8秒 | 1.4秒 | -0.4秒 |
総合スコア | 99 | 100 | +1(満点) |
シミュレーションでは、フォントトラフィックが4.0MBから79KBへ3.92MB削減されたことで、LCPが0.7秒、FCPが0.6秒それぞれ短縮され、総合スコアが満点に到達した。3.88MBのMaterial Symbols Outlinedがネットワーク帯域を圧迫し、ページ全体のリソース読み込みに影響を与えていたことがこの結果から読み取れる。
アイコンフォントをそのまま使い続けたい場合でも、実際に使用するアイコンだけを含んだサブセットを自社ドメインから配信することで、本シミュレーションに近い大幅な削減効果を得られる可能性がある。
詳細はロコンドのボトルネック研究にまとめている。
Hamee本店: 使われていないNoto Sans JPがレンダリングをブロック
スマートフォンケース・アクセサリーの専門店Hamee本店では、Google FontsからNoto Sans JP(ウェイト400/700)が読み込まれていた。しかしCSS内にNoto Sans JPの font-family 参照が一切存在しなかった。229KBのCSSが読み込まれ、外部ドメイン(fonts.googleapis.com)へのリクエストも発生していたにもかかわらず、実際のレンダリングには使用されていなかったと思われる状況だ。
対処はシンプルで、使われていないGoogle Fontsの <link> 要素を削除するだけだ。CSSで参照されていないフォントのため、ページの見た目に変化はない。この削除を適用したシミュレーションの結果が以下だ。
| 指標 | 解消前 | 解消後(シミュレーション) | 変化量 |
|---|---|---|---|
FCP | 0.8秒 | 0.4秒 | -0.4秒 |
LCP | 1.4秒 | 1.2秒 | -0.2秒 |
SI | 1.9秒 | 1.7秒 | -0.2秒 |
この229KBのCSSはレンダリングブロックリソースとして検出されていたため、削除によってレンダリング開始を前倒しでき、シミュレーションではFCPが0.4秒短縮された。使われていないにもかかわらずレンダリングをブロックしていた点が、このケースで注目すべき特徴だ。
詳細はHamee本店のボトルネック研究にまとめている。
そもそもWebフォントを使うべきか
対処の手段を見る前に、一段大きな問いがある。そのページに本当にWebフォントが必要か、という問いだ。
整ったWebフォントでブランドの世界観を表現したい。その心情は理解できる。だが日本語はWebフォントのデータ量という点でどうしても不利な立場にある。数千から数万字を抱える以上、英語のように軽くは済まない。理不尽な面もあるが、これは致し方ないところだ。
とりわけ通販サイトやメディアサイトでは、商品や記事といったコンテンツそのものが主役だ。世界観を伝えるデザインを価値の中心に据えるサイトとは事情が違う。コンテンツが快適に読めればよいのなら、数MBのフォントを読み込んでまでWebフォントにこだわる必要は薄い。コストが見合わない場面も多いはずだ。少なくとも弊社はそう考えている。
とはいえこれは想像だけで結論を出せる話ではない。いちばん確実なのは、WebフォントとシステムフォントでABテストを行い、どちらがコンバージョンや滞在につながるかを実際に比べることだ。弊社は通販・メディア用途でのWebフォントの必要性を低いと見ている。ただし最終的な判断はサイトごとのデータに委ねるのが筋だろう。まず計測し、白黒をつけてから決めればよい。
自分のサイトで対処するには
日本語Webフォントへの対処は、問題の性質によっていくつかの方向がある。
まず未使用フォントを探す
Hamee本店の例のように、実際には使われていないフォントが読み込まれているケースは意外と多い。Chrome DevToolsの「カバレッジ」機能や、LighthouseのレポートでUnused CSSの指摘がないかを確認するとよい。CSSで参照されていないフォントは削除するだけでよく、見た目に影響しない。まずここから確認したい。
font-display: swap でFOITを防ぐ
font-display: swap を指定すると、フォントが読み込まれるまでの間は代替フォント(システムフォント)で一時的に描画し、ダウンロード完了後に切り替える。フォントファイルの転送量そのものは変わらないが、「フォントが届くまで何も描画しない」状態を避けられるため、FCPの改善につながることがある。
@font-face {
font-family: 'Noto Sans JP';
font-display: swap; /* 追加 */
src: url('...') format('woff2');
}Google Fontsで配信する場合はURLに &display=swap を付与する。
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">サブセット化で転送量を削減する
日本語フォントを使い続けるのであれば、サブセット化が最も効果的な転送量削減手段だ。実際に使用する文字だけを含んだフォントファイルを作成すれば、ECサイトのトップページで使う文字が500字程度であれば数MB全体を転送する代わりに数十KBで済む可能性がある。
アイコンフォントも同様で、使用するアイコンだけを含むサブセットを作成し自社ドメインから配信することで、ロコンドの例に近い大幅な削減を得られる可能性がある。
なおGoogle Fontsはもともとページで実際に使われている文字だけを含んだサブセットを動的に生成して配信する仕組みを持っている。ただし外部ドメインへの接続コストは残る。
読み込むウェイトを絞る
必要以上に多くのウェイト(太さ)を読み込んでいるサイトもときどき見かける。日本語フォントはウェイトごとに別ファイルで、それぞれが数百KB〜MB級だ。RegularとBoldとMediumを並べるだけで、転送量はあっという間に積み上がる。
どうしても日本語Webフォントを使うなら、本当に必要なウェイトだけに絞りたい。あるいはバリアブルフォントを採用する手もある。バリアブルフォントは1つのファイルで太さを連続的に変えられるため、複数のウェイトを別々に読み込む必要がなくなる。
preconnect で接続コストを前倒しする
Google Fontsを使う場合、フォントCSSと実際のフォントファイルが別ドメイン(fonts.googleapis.com と fonts.gstatic.com)から配信される。preconnect を指定しておくとDNSルックアップとTLSハンドシェイクのコストを前倒しできる。
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>転送量は変わらないが、接続確立のオーバーヘッドをあらかじめ済ませておく効果がある。
システムフォントへの切り替えを検討する
いずれの対処も採用しにくい場合は、日本語Webフォントをやめてシステムフォントにフォールバックすることも選択肢だ。macOSの「ヒラギノ角ゴ」やWindowsの「游ゴシック」など、モダンなシステムフォントは品質が高く、Webフォントとの差がそれほど目立たないケースも多い。
e☆イヤホンのシミュレーションがこのアプローチで実施された。見た目の変更を前提とする大きな判断だが、パフォーマンスへの効果は実例が示すとおりだ。
まとめ
- 日本語Webフォントは数MB単位になりやすい。 文字種の多さからファイルサイズが英語フォントと桁違いになるため、転送コストがページ全体の読み込みに影響することがある。e☆イヤホンでは、6.05MBのフォントがページの転送量を43%押し上げていたことがシミュレーションから推定された。
- FCPとLCPへの影響が大きい。 フォントCSSはレンダリングブロックリソースになりやすく、
font-display未設定のままでは描画が大きく遅れる場合もある。ルタオの例では、フォント削除だけでLCPが2.8秒から0.2秒へと93%短縮されるというシミュレーション結果が得られた。 - 未使用フォントは削除するだけでよい。 Hamee本店の例のように、CSSで参照されていないフォントが読み込まれていることがある。見た目に影響せず削除できるため、まずここから確認したい。
- アイコンフォントも要注意。 ロコンドの例のように、アイコン用途でも全文字セットを読み込む構成では数MBの転送が発生する。使用するアイコンのサブセットだけを配信する形に変えることで大幅な削減が期待できる。
- 対処の選択肢は複数ある。
font-display: swapでFOITを防ぐ、サブセット化や使うウェイトの絞り込み(バリアブルフォント)で転送量を削減する、preconnectで接続コストを前倒しする、あるいはシステムフォントに切り替えるという選択肢がそれぞれある。効果の性質が異なるため、問題の性質に合わせて選ぶのがよい。 - 通販・メディアサイトではそもそもの要否も検討したい。 これらのサイトはコンテンツが主役であり、世界観デザインを中心に据えるサイトとは事情が違う。数MBのコストに見合うかは、WebフォントとシステムフォントのABテストでコンバージョンを比べて判断するのが確実だ。弊社は要否を厳しく見ている。ただ最終判断は計測したデータに委ねたい。
Webフォントの最適化はサイトのデザイン方針と密接に関わる。全体を一律に削除や切り替えで対処するのが難しいとしても、未使用フォントの削除や font-display: swap の設定は見た目の変更なしに進められる。まずそこから始めるのが現実的だろう。
自社サイトのWebフォント設定や他のボトルネックを体系的に調べたい場合は、弊社の表示速度ボトルネック研究 vigilanteの事例が参考になる。より詳しい調査が必要な場合はアイデアマンズまでご相談いただきたい。