Webフォントを使うためのベストプラクティス(最もパフォーマンスがよい、遅延が少ない)をGoogle Fontsの利用を中心に考えてみたいと思います。
形式
EOT・TTF・WOFF・WOFF2・SVG等ありますが、2019年12月現在、ほとんどのブラウザでWOFFとWOFF2がサポートされていますので、この2つを読み込めばOKです。
※但し、案件ごとのターゲットブラウザは確認しましょう。
Google FontsのCDN利用
Google Fontsをタグで読み込んで使う場合、複数フォントを読み込むと以下のようなタグが発行されます。
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP:400,700|Roboto:400,700&display=swap&subset=japanese" rel="stylesheet">
W3Cのチェッカーでエラーでますので、文法エラー回避のためには、|
でなく%7C
を使います。
- メリット
- 楽に使える
- デメリット
- レンダリングブロックが発生する
- ファイルパスが変わる可能性がある
発生しやすい問題
FOUT(Flash of Unstyled Text)
Webフォントの読み込みが完了するまで代替フォントで表示され、読み込みが完了するとWebフォントに切り替わる現象。
Chromeなどのブラウザはタイムアウトまでにロードが完了しなかった場合、代替フォントが表示され、フォントダウンロード後に指定フォントに切り替わるため、そのときにチラつきが発生する問題。
FOIT(Flash of Invisible Text)
Webフォントの読み込みが完了するまで、テキストが表示されない現象。
Safariではフォントのロードを待ち続けるように実装されているため、フォントのダウンロードが完了するまでテキストが表示されなくなる問題。
CSSによる最適化
前項のように、ブラウザによって挙動の違いがあり、FOUTやFOITのような問題が発生する場合があります。
font-display
プロパティは、フォント読込中の挙動をCSSから制御することができます。
- メリット
- レンダリンクブロックが発生しない(非同期読み込み)
- 細かくフォントの挙動を制御できる
- Edge、IEでの利用可能
-
auto
は、ブラウザのデフォルトの挙動です。 -
block
は、タイムアウトがなくなるため、FOUTはなくなるが、FOITが発生しやすくなります。 -
swap
は、ブロック期:0秒、スワップ期:無限で、FOITはなくなるが、FOUTが発生しやすくなります。 -
fallback
は、ブロック期:0.1秒、スワップ期:3秒で、フォールバックフォント表示が許容される場合に使用します。 -
optical
は、ブロック期:0.1秒、スワップ期:0秒で、FOUTは発生せず、FOITも最小限です。ただし、フォントを取得するかどうかブラウザ任せになるため、早いテキスト表示を優先する場合に使うとよいです。
JavaScriptによる最適化
Font Loading API
フォントのダウンロード進行状況の監視や挙動の制御ができるが、ブラウザの実装に差があるため、次に紹介するWeb Font Loaderのほうが使いやすいです。
Web Font Loader
GoogleとTypekitが共同開発したフォントの読み込みを制御できるJavaScriptライブラリ。ソースコードはGitHubで公開されており、無料で利用できます。使い方はNoto Sans JPの使用例にて後述します。
preloadによる最適化
- メリット
- Web Font Loaderより読み込み(レンダリング)が早い
- AMPでも利用可能
- デメリット
- IE、Firefox非対応
- CDNは使えない
- FOUTが発生する可能性はある
@font-face {
font-family: "YakuHanJP_Noto";
font-weight: 700;
font-style: normal;
src: url("/assets/fonts/yakuhanjp/YakuHanJP-Bold.woff2") format("woff2"), url("/assets/fonts/yakuhanjp/YakuHanJP-Bold.woff") format("woff");
font-display: swap;
}
}
### sessionStorageの使用
ブラウザを閉じるまで、ページ遷移してもWebフォントを再読み込みする無駄が発生しないようにしています。
### 非同期の読み込みファイルはscriptタグで記述
GithubのREADMEの記述は、スクリプトインジェクション等の可能性があり、脆弱性の観点からあまりよい記述でないといえます。シンプルにscriptタグのasync属性を利用したコードで記述しています。
また、非同期で読み込んだ場合、WebFont.load()が実行されるタイミングでWeb Font Loaderの読込が完了していない可能性があるため、WebFontのtypeofをチェックして未完了の時は実行されないようにしています。
### Noto Sans JPで気になる約物はYaku Hans JPを使用
半角の約物だけのWebフォントで、Noto Sansに最適化されたフォントファイルもあります。
[https://github.com/qrac/yakuhanjp](https://github.com/qrac/yakuhanjp)
_例としてYaku Hansにはpreloadを使っていますが、WebFontLoaderでも記述できます_
## 参照元
[ウェブフォントの最適化 | Web Fundamentals | Google Developers](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#_7)
_「ブラウザによる挙動の違い」の掲載内容は、参照元から転用させていただいています。_