Webフォントはデザインの道具という印象が強く、表示速度の議論では画像やJavaScriptより後回しになりがちです。しかし日本語Webフォントは事情が違います。
アイデアマンズは通販サイトを中心にサイトスピード改善を手がけています。その現場で、日本語Webフォントが表示を大きく遅らせている例を何度も見てきました。
この記事では実在する4つのECサイトの計測結果をもとに、日本語Webフォントの影響と具体的な対処コードを紹介します。
日本語フォントはなぜ重いのか
理由はシンプルです。数百字で足りる英語フォントに対し、日本語は漢字まで含めて数千から数万字を抱えます。その差がそのままファイルサイズに表れます。
Noto Sans JPのような一般的な日本語フォントは、フルセットだと1ウェイトでも1.5〜2MBほどです。複数ウェイトをそろえれば数MBに達します。
さらにブラウザは、Webフォントの到着を待って該当部分の描画を止めることがあります。FOIT(Flash of Invisible Text)と呼ばれる挙動です。font-display を指定しないとこれが起きやすく、FCPやLCPの遅延につながります。
実在4サイトの計測
弊社の表示速度ボトルネック実例研究では、ボトルネックを1つずつ切り分けてbefore/afterをシミュレーションしています。日本語Webフォントが要因になった4サイトを見ていきます。
e☆イヤホン: 6.05MBのフォント転送
イヤホン専門店のトップページでは、Noto Sans Japaneseの3ウェイト(Regular / Semi-Bold / Bold)が読み込まれていました。フォントの合計は6.05MBに達していました。
@font-face を削除してシステムフォントスタックにフォールバックしたところ、フォント転送は6.05MBから62.1KBへ99%削減されました。ページ全体の転送量も14.0MBから8.0MBへ43%減っています。
| 指標 | 解消前 | 解消後 |
|---|---|---|
| SI | 3.3秒 | 1.7秒 |
| 総合スコア | 99 | 100 |
SI(Speed Index)は3.3秒から1.7秒へ48%短縮されました。LCP要素は画像だったためLCPの数値は動きませんでしたが、体感の読み込みに与える影響の大きさが読み取れます。
ルタオ: 933msのレンダリングブロック
洋菓子店の公式オンラインショップでは、Google FontsからNoto Serif JPを読み込んでいました。このフォント関連のリソースが描画の主要なボトルネックになっていました。
Google Fonts CSSによる933ms相当の描画遅延、150KBの未使用CSS、14個のwoff2ファイルの転送コストが重なっていました。
Google Fontsの読み込みを外し、システムフォントに置き換えたときの数値です。
| 指標 | 解消前 | 解消後 |
|---|---|---|
| LCP | 2.8秒 | 0.2秒 |
| FCP | 1.4秒 | 0.2秒 |
| SI | 2.2秒 | 1.2秒 |
LCPは2.8秒から0.2秒へ93%短縮されました。フォントのレンダリングブロックと転送コストが、LCPの大部分を押し上げていたことがわかります。
ロコンド: アイコンフォント3.88MB
靴・ファッションの通販サイトでは、Google FontsからMaterial Symbols Outlinedが読み込まれていました。日本語ではなくアイコン用途のフォントで、サイズは3.88MBでした。
アイコンフォントは文字コードにアイコンを対応付ける仕組みです。使うアイコンが数十種類でも、全文字セットをそのまま配信するとフォント転送は数MBに達します。
Google Fonts関連の link を削除した計測では、フォント転送が4.0MBから79KBへ減りました。LCPは1.8秒から1.1秒、FCPは1.6秒から1.0秒へ短縮され、総合スコアは満点に届いています。
Hamee本店: 使われていないフォント
スマートフォンケースの専門店では、Google FontsからNoto Sans JPが読み込まれていました。ところがCSS内にこのフォントの参照が一切なく、実際には使われていませんでした。
それでも229KBのCSSがレンダリングブロックリソースとして読み込まれ、外部ドメインへのリクエストも発生していました。使われていない <link> を削除するだけで、見た目を変えずにFCPを0.8秒から0.4秒へ短縮できました。
対処のコード
4つの例からわかるのは、対処の方向が問題の性質で変わることです。実装しやすい順に紹介します。
まず未使用フォントを探す
Hamee本店のように、使われていないフォントが読み込まれている例は意外と多いものです。Chrome DevToolsの「カバレッジ」機能や、LighthouseのUnused CSSの指摘で確認できます。CSSで参照されていないフォントは、削除しても見た目に影響しません。
font-display: swap でFOITを防ぐ
font-display: swap を指定すると、フォントが届くまでは代替フォントで描画し、完了後に切り替えます。転送量そのものは変わりませんが、描画開始の遅れを避けられます。
@font-face {
font-family: 'Noto Sans JP';
font-display: swap;
src: url('/fonts/NotoSansJP.woff2') format('woff2');
}
Google Fontsで配信する場合はURLに &display=swap を付けます。
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
サブセット化で転送量を削る
日本語フォントを使い続けるなら、サブセット化が最も効きます。実際に使う文字だけを含むフォントを作れば、トップページで使う文字が500字程度のとき、数MBが数十KBまで下がる可能性があります。
アイコンフォントも同じです。使うアイコンだけのサブセットを自社ドメインから配信すれば、ロコンドの例に近い削減が見込めます。
読み込むウェイトを絞る
日本語フォントはウェイトごとに別ファイルで、それぞれ数百KBからMB級です。RegularとBoldとMediumを並べるだけで転送量が積み上がります。本当に必要なウェイトだけに絞るか、1ファイルで太さを変えられるバリアブルフォントを検討します。
preconnect で接続コストを前倒しする
Google Fontsは、CSSとフォントファイルが別ドメインから配信されます。preconnect を指定すると、DNSルックアップとTLSハンドシェイクを前倒しできます。
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
そもそも必要かも問う
対処の前に、一段大きな問いがあります。そのページに本当にWebフォントが必要か、という問いです。
通販サイトやメディアサイトでは、商品や記事といったコンテンツが主役です。世界観をデザインで伝えるサイトとは事情が違います。数MBのフォントを読み込んでまでWebフォントにこだわる必要は、それほど高くないと弊社は見ています。
とはいえ想像だけで決める話ではありません。WebフォントとシステムフォントでABテストを行い、コンバージョンや滞在で比べるのが確実です。まず計測してから判断すればよいはずです。
まとめ
- 日本語Webフォントは数MBになりやすく、e☆イヤホンでは6.05MBがページ転送量を43%押し上げていました
- フォントCSSはレンダリングブロックになりやすく、ルタオではフォント削除だけでLCPが2.8秒から0.2秒へ短縮されました
- 使われていないフォントはHamee本店のように削除するだけでよく、見た目に影響しません
- アイコンフォントも要注意で、ロコンドでは3.88MBのアイコンフォントが転送を圧迫していました
- font-display、サブセット化、ウェイト削減、preconnectと、問題の性質に合わせて対処を選ぶ
まず着手しやすいのは、未使用フォントの削除と font-display: swap です。どちらも見た目を変えずに進められます。

