弊社サイトでは3種類のWebフォント(font-weight的には8タイプ)を使用しております。
【'Noto+Sans+JP:400,700', 'Noto+Sans:400,700', 'Raleway:200,400,500,700'】
全てライセンスフリーの Google Fonts です。
Googleさん!ありがとう!!
ひじょうに助かります。お世話になっております。足を向けて寝られません!
その Google のエラい人が、来年あたりに検索結果に反映させると明言している Web Vitals ※1 対策と、画面表示の際に 一瞬チラつく ※2 問題を解消するためには、Webフォントをどのように実装するのがベストなのかを、実際に本番環境へ反映し検証してみました。
検証の最終目標は下記となります。
※優先順位はありませんがイイ感じに折り合いが付くように、検証と調整を行う前提
説明するまでもないと思いますが、日本語 NotoSans を例として実装方法を解説します。
head 内にて linkタグで読み込む場合
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
css から @import で読み込む場合(超遅いから非推奨)
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap");
css での font-family 設定
font-family: "Noto Sans JP";
JavaScript を利用して非同期読み込みするヤーツ
WebFontConfig = {
google: { families: ['Noto+Sans+JP:400,700', 'Noto+Sans:400,700', 'Raleway:200,400,500,700'] }
};
(function() {
var wf = document.createElement('script');
wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
'://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
2行目の families で読み込むフォントを指定します。
上記見本のようにフォントや font-weight は『,(カンマ)』繋ぎで複数指定できます。
Webフォント読み込み終了時、html に class名『wf-active』が付与される仕様となっており、FOUT 対策として読み込みが終了してからテキストを表示するようにcssにて設定をしてみた。
html{
visibility:hidden;
}
html.wf-active{
visibility:visible;
}
当然、通信環境にも左右されるとは思いますが、我が家の環境では非表示時間も一瞬ですし、画面表示時のチラつきは全くなくなり、個人的にはストレスを感じなくなりました!
「完璧じゃないっすかコレ!」って思ったのですが…Google さんから激しく怒られました…
「ユーザビリティとか通信環境とか考えて!テキストを非表示させるとか、マジありえないからっ!真っ白って!」ってニュアンスで><
rel="preload" を head 内で設定することで、ブラウザの主なレンダリング機構が起動する前(画面描画ライフサイクルの早期)から、非同期読み込みができ、レンダリングをブロックしにくくなります。
実装の段取りとして、まずは先行して読み込むフォントファイルをどうするか?という話になります。
Google Fonts のフォントファイル(woff とか eot とか)は fonts.gstatic.com にあるようですが、仕様変更などによって流動的な URL であることと、woff2ファイルに関しては相当数分割(サブセット化)されていることから、基本的には自サーバにフォントファイルを配置し @font-face にて読み込むのが、正しいと今回の検証では判断しました。
上記サイトへアクセス後、使用するフォントを検索し詳細画面を表示させ、画面右上の方にある 『Download family』 を押下し圧縮ファイル(.zip)をダウンロードします。
解凍すると otf(OpenTypeFont)ファイル と ライセンステキスト が展開されます。
ちなみに解凍された otf (日本語 NotoSans)ファイルサイズは 4,684Kb ありました…日本語フォント恐るべし
続いては『拡張子を何にするか問題』です。
対応ブラウザだけから判断すると woff ファイルだけでも良いように思いますが、woff2 ファイルだと更に10%以上のファイルサイズダイエットが出来るようですし、今後は woff2 ファイルに対応するブラウザは増えていくと予想出来ましたので、弊社サイト対象ブラウザバージョンとの兼ね合いなども考慮して、woff・woff2 としました。
上記アプリケーションを使用して otf から woff にコンバートした結果、ファイルサイズは 1,885Kb まで落ちました。
半分以下になったものの、弊社サイトでは日本語フォントを『400(normal)』と『700(bold)』の2種類を使用しているため、純粋に日本語フォントを表示させるためだけに 3.5Mb ものファイルをダウンロードさせなければなりません><
実際にこの状態で検証してみたところ『Speed Index』『Largest Contentful Paint』『Time to Interactive』このあたりの数値が強烈に悪化しました…もちろん Web Vitals 的にマイナスです。
当然、流れ的に 日本語フォントのサブセット化(ファイルサイズダイエット) を施策しました。
サブセット化とは『使わないであろう文字をフォントファイルの中から除外する』ってことです。
普通に考えたら難しそうな作業っぽいですが、世の中にはとても便利なアプリケーションがあり、またそれを無料で提供してくださる徳の高い方々がいらっしゃいます。
上記アプリケーションを使用して 第一水準漢字・記号・ローマ字・カタカナ・ひらがな までに絞り込んだ結果、1,885Kb から 555Kb まで落ちました!
これはかなり現実的なラインです。
<link rel="preload" as="font" href="/fonts/NotoSansJP700.woff2" crossorigin>
<style>
@font-face {
font-family: 'Noto Sans JP';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('/fonts/NotoSansJP700.woff2') format('woff2'),
url('/fonts/NotoSansJP700.woff') format('woff');
}
</style>
上記URL で確認できる通り rel="preload" を認識できないブラウザは、woff2 を認識できませんので 『preload するのは woff2 のみで良い』 と判断でき、上記のように woff2 のみ preload しました。(実際には3種類・8タイプの Webフォントを先読みしています)
fonts.googleapis 検証その1 | Web Font Loader 検証その2 | preload 検証その3 | |
---|---|---|---|
Performance | 96点 | 100点 | 96点 |
First Contentful Paint | 0.5s | 0.4s | 0.3s |
Speed Index | 0.9s | 0.7s | 0.7s |
Largest Contentful Paint | 1.3s | 0.6s | 1.4s |
Time to Interactive | 0.5s | 0.4s | 0.3s |
Total Blocking Time | 0ms | 0ms | 0ms |
Cumulative Layout Shift | 0.015 | 0.008 | 0.007 |
パッと見ではどのように実装しても大差はないように思います。
※『Performance』以外は数値が小さいほど優秀
大きく違うのは 『preload』 の場合は GoogleCDN を使用していないという点で、Google さんのチカラを借りずに、重たくて表示速度改善には不向きといわれる 日本語 Webフォント を自サーバからダウンロードさせていてこの数値ということです。
デフォルトのフォントセットを使用した時は『Speed Index』『Largest Contentful Paint』『Time to Interactive』あたりの数値が大きく悪化しましたが、サブセット化施策後は低く抑えることができています。
そして、なにより『preloadを利用してフォントファイルを先読み』を実装した一番の収穫ポイントは『チラつき( FOUT )を極力なくす』ことに成功したことですね!
SEO 的速度改善は勿論大事ですが、画面表示した際に『チラつく』『カクつく』方が個人的には気になっていたので( ̄^ ̄)ゞ
本記事はあくまでも弊社サイトにて、実際に検証してみた所感・数値をまとめたものです。
検証内容に関してもザックリと3つに分けておりますが、細かく分けるとかなりのトライ・アンド・エラーを繰り返しております。(関係ないけど『トライアルアンドエラー』が正しいらしい)
そして、全てのサイトに当てはまる結果ではありません。
優先順位によっても違った実装方法になると思いますし、サイト特性や使用フォントによっても然りです。
なので、1つの参考程度にお読みいただけたらと思います。