メインコンテンツまで移動する

Web Font Loader で Google Fonts を非同期で読み込みサイト速度を改善

  • 公開日
  • 更新日

Akira Web クリエイター

この記事の内容は古く、現在は参考にできません。Web フォントの最適な読み込み方法については、Google の Chrome チームが解説する フォントに関するおすすめの方法 をご参考ください。

はじめに

デバイスを問わず、表示させたいフォントを表示できるのが Google Fonts です。また、豊富な種類を無料で利用できるのも嬉しいポイント。

さらに、2018 年 9 月 28 日より、それまでアーリーアクセス版だった日本語フォントが正式版として提供されました。

しかし、サイト表示が遅くなるデメリットがあります。遅くなる原因の 1 つが、レンダリングをブロックしてしまうこと。

そこで Web Font Loader を使い、非同期で読み込む方法をご紹介します。Web Font Loader を使えば、レンダリングをブロックせずに Google Fonts を利用できます。

尚、CSS の @import で Web フォントを読み込むのは、おすすめできません。サイト表示が遅くなります。

Web Font Loader ではなく rel="preload" で先読みする方法もあります。やり方は、Google Fonts を preload で先読みし最適化 で解説しています。

Web Font Loader とは?

Web Font Loader は、Google と Typekit が共同開発したフォントの読み込みを制御する JavaScript ライブラリです。

ソースコードは GitHub で公開されており、無料で利用できます。

また、Binar::Apps が紹介している FOUT with Web Font Loader が、おすすめの使い方(現在は記事が削除されています)。この記事では、sessionStorage を使い Web Font Loader を利用しています。そのため、サイト訪問者がブラウザを閉じるまで、ページを移動しても Web フォントを再読み込みする無駄が生じません。

使い方

Web Font Loader の使い方は、非常に簡単です。

Google Fonts で公開されているフォントは、フォント名を指定するだけで非同期で読み込めます。

Roboto の Regular 400 を読み込ませる場合は、下記のコードを用います。

window.WebFontConfig = {
  google: { families: ['Roboto'] },
  active: function () {
    sessionStorage.fonts = true;
  },
};

(function () {
  var wf = document.createElement('script');
  wf.src = 'https://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 行目の google: { families: ['Roboto'] }'Roboto' で使用するフォントを指定します。

正式版となった 日本語フォント も指定できます(下記のコードで指定しているのは Noto Sans Japanese)。

window.WebFontConfig = {
  google: { families: ['Noto+Sans+JP'] },
  active: function () {
    sessionStorage.fonts = true;
  },
};
以下同じ;

複数のフォントウェイトの指定も可能です。

window.WebFontConfig = {
  google: { families: ['Roboto:400,500,700'] },
  active: function () {
    sessionStorage.fonts = true;
  },
};
以下同じ;

カンマ , で区切れば、2 つ以上の Google Fonts を指定できます。

window.WebFontConfig = {
  google: { families: ['Roboto:400,500,700', 'Noto+Sans+JP'] },
  active: function () {
    sessionStorage.fonts = true;
  },
};
以下同じ;

指定するフォント名は、HTML で呼び出す際のコードを参考にします。例えば、普通に Noto Sans JP を読み込ませる場合は、下記の HTML を使います。

<link
  href="https://fonts.googleapis.com/css?family=Noto+Sans+JP&display=swap"
  rel="stylesheet" />

https://fonts.googleapis.com/css?family= の後の Noto+Sans+JP が使用するフォント名です。

Material icons も、Web Font Loader を使い非同期で読み込めます。

window.WebFontConfig = {
  google: { families: ['Material+Icons'] },
  active: function () {
    sessionStorage.fonts = true;
  },
};
以下同じ;

アーリーアクセス版の読み込み方法

2016 年 10 月から 9 種類のフォントが公開されているのが、アーリーアクセス版の Google Fonts 日本語 です。

このうち、「はんなり明朝」「こころ明朝」「ニコモジ」「ニクキュウ」の 4 つのフォントは、正式版では提供されていません。

この 4 つのアーリーアクセス版のフォントを使う場合も、Web Font Loader を利用できます。ただし、正式版とアーリーアクセス版は URL が異なるため、ほんの少し手間が増えます。

ニコモジを読み込む場合のコードは、下記のとおりです。

window.WebFontConfig = {
  custom: {
    families: ['Nico Moji'],
    urls: ['https://fonts.googleapis.com/earlyaccess/nicomoji.css'],
  },
  active: function () {
    sessionStorage.fonts = true;
  },
};

(function () {
  var wf = document.createElement('script');
  wf.src = 'https://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);
})();

正式版の Google Fonts は、google: { families: [] } でフォント名を指定します。

一方、アーリーアクセス版のフォントは、custom: { families: [] } でフォント名を指定します。

フォント名は、CSS の font-familyNico Moji を使います。HTML で呼び出すコード内の nicomoji で指定すると、読み込み速度が低下しました。これは、その他のアーリーアクセス版フォントでも同様です。

HTMLの nicomoji は使わない
<link
  href="https://fonts.googleapis.com/earlyaccess/nicomoji.css"
  rel="stylesheet" />

さらに、3 行目の urls: [] で URL の指定が必要です。

正式版とアーリーアクセス版を同時に読み込ませる方法

正式版とアーリーアクセス版の Google Fonts は、同時に読み込めます。

window.WebFontConfig = {
  google: { families: ['Roboto:400,500,700', 'Noto+Sans+JP'] },
  custom: {
    families: ['Nico Moji'],
    urls: ['https://fonts.googleapis.com/earlyaccess/nicomoji.css'],
  },
  active: function () {
    sessionStorage.fonts = true;
  },
};

(function () {
  var wf = document.createElement('script');
  wf.src = 'https://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);
})();

google: { families: [] }custom: { families: [] } も指定します。

CSS で font-family を指定

あとは、CSS の font-family を指定すれば、Google Fonts を表示できます。

body {
  font-family: 'Roboto', sans-serif;
}

Noto Sans JP を使う場合には、この指定方法がいいかもしれません。Noto Sans JP より Noto Sans CJK JP を優先して表示する指定です。

body {
  font-family: 'Noto Sans CJK JP', 'Noto Sans JP', sans-serif;
}

理由は、Android と Chrome OS のシステムフォントに Noto Sans CJK JP が採用されているためです。ローカルにあるフォントファイルの使用で、フォントが素早く表示されます。また、Noto Sans JP と Noto Sans CJK JP は、書体がほぼ一緒です。書体の違いに気付く方は、あまりいらっしゃらないと思います。

FOUT(ちらつき)を CSS で制御

Google Fonts に限らず、Web フォントを非同期で読み込む際は FOUT と呼ばれるちらつきが生じます。

FOUT とは以下の動画のように、フォントが途中で変わる現象です。

この FOUT が起きる原因は、Web フォントの読み込みが完了するまで、スタイルが適用されていないテキストが表示されるためです(動画では、動画撮影に使った Chromebook のローカルフォント Noto Sans CJK JP が最初に表示されている)。

そして、読み込みが完了すると Web フォントに変わります(動画では、読み込んだ Sawarabi Mincho に変わっている)。

さらに日本語の Web フォントは、フォントの切り替わりに少しタイムラグが生じます(切り替わり時に一瞬テキストが消える)。

Web Font Loader は、この FOUT の対策も可能です。

Web Font Loader は、フォントイベントに対応したクラス名を <html> タグに追加します。追加されるクラス名のうち、CSS で主に利用するのは下記のものです。

  • .wf-loading:フォントを読み込み中の時に追加
  • .wf-active:フォントの読み込みが完了した時に追加
  • .wf-inactive:フォントの読み込みに失敗、またはブラウザが Web フォントに対応していない時に追加

他にフォント毎に追加される3つのクラス名もありますが、CSS ではあまり使わないため省略しています。詳しくは GitHub 内の Events をご覧ください。

この <html> タグに追加されるクラス名を使い、CSS を指定します。

h2 {
  font-family: 'Sawarabi Mincho';
  visibility: hidden;
}

.wf-active h2 {
  visibility: visible;
}

上記の CSS は h2 の見出しに Sawarabi Mincho を指定し、まずは非表示にしています。ただし、display: none; での非表示ではないため、レイアウトは崩れません。

フォントの読み込みが完了し <html> タグのクラスに .wf-active が追加されると、visibility: visible; で h2 を表示しています。

この CSS を指定すると、下の動画のように表示されます。

Web フォントの読み込みが完了するまでテキストは表示されないため、フォントが切り替わりません。この CSS での FOUT の制御は、Adobe のフォントイベント が紹介している方法です。

ただし、この方法は、意図的に FOIT を発生させるものです。FOIT とは、最初はテキストが表示されず、Web フォントの読み込み後に突然テキストが表示される現象です。

FOUT より FOIT を嫌う方は多いため、どうしてもローカルフォントでの表示を避けたい箇所でのみの使用がいいかもしれません。

例えば、Instagram のようにサイトタイトルに独特の Web フォントを使っている場合は、そのフォントがブランディングに一役買っているはずです。そのような場合は、ローカルフォントでの表示は避けるべきかもしれません。

もっと細かく FOUT を制御

Adobe は、より細かく CSS を指定する方法も紹介しています。例えば、こんな感じです。

h2 {
  font-family: Georgia, serif;
  font-size: 25px;
  letter-spacing: 1px;
  position: relative;
  top: 2px;
}

.wf-active h2 {
  font-family: Vollkorn, serif;
  font-size: 24px;
  letter-spacing: 0;
}

.wf-active h2 に、最終的に表示する Google Fonts の Vollkorn を指定しています。

それに加え h2 に、Vollkorn が読み込まれるまで Georgia を表示するよう指定しています。さらにフォントサイズや字間、位置も調整します。

この指定をすると、下記の動画のように FOUT を抑えることが可能です(完全に制御すると動画で判別できないため、FOUT が分かるようにしています)。

読み込みたい Web フォントに似たフォントを最初に表示することで、FOUT を抑えます。似たフォントを探す手間がかかりますが、テキストは瞬時に表示したい場合に適しています。

フォローする