Google Fonts を非同期で読み込みサイトスピードを高速化

Web Font LoaderでGoogle Fontsを遅延読み込み

Akira

福岡在住ウェブデザイナー。Web サイト制作に役立つ情報を「見やすさ」と「使いやすさ」にこだわり紹介しています。

デバイスを問わず、表示させたいフォントを表示できるのが Google Fonts です。

また、豊富な種類を無料で利用できるのも嬉しいポイント。

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

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

そこで Web Font Loader を使い、非同期で読み込む方法をご紹介します。

Web Font Loader を使えば、レンダリングをブロックせずに Google Fonts を利用できます。

よりサイトを高速化したい場合には、Web Font Loader ではなく rel="preload" で先読みする方法がおすすめです。使い方は、下記のページで解説しています。

AMP にも対応!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 の使い方

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

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

Roboto の regular 400 を読み込ませる場合には、下記のコードを用います。 JavaScript を書くファイルに追加するか、 <script></script> で囲みインラインで記述します。

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 JP )。

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" rel="stylesheet">

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

そのままコピペをすれば OK 。簡単です。

ちなみに、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 を使う場合には、この指定方法がおすすめです。

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

Noto Sans JP より Noto Sans CJK JP を優先して表示する指定です。

これは、Android と Chrome OS のシステムフォントに、Noto Sans CJK JP が採用されているためです。

ローカルにあるフォントファイルを使うことで、フォントが素早く表示されます。

しかも、Noto Sans JPNoto 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; での非表示ではないため、レイアウトは崩れません。

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

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

Web フォントの読み込みが完了するまでテキストは表示されないため、フォントが切り替わることがなくなります。

この CSS での FOUT の制御は、 Adobe のフォントイベントが推奨している方法です。

<body> タグに Google Fonts を指定する場合には、ファーストビュー内のテキストに CSS で FOUT 対策を行うといいかもしれません。

もっと細かく 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 は発生しています。しかし、お互い似た書体であるため、ちらつきをだいぶ抑えられています。 letter-spacing をもっと突き詰めれば、さらにちらつきは抑えられるはず。

似たフォントを探す手間がかかりますが、テキストは瞬時に表示したいとお考えの方に適しています。


Google Fonts は、サイトにアクセントを加えてくれます。また、テキストが読みやすいサイトになるのも大きな魅力です。

しかし、サイト表示の速度を犠牲にしては、サイト訪問者を失望させます。

美しさも速さも両立させるために、Web Font Loader を利用されてはいかがでしょうか。

<link rel="preload"> でフォントファイルを読み込んでも、サイト表示は高速化します。ただ、IE が未対応。

Web Font Loader であれば、IE にも対応できます。

また、FOUT を制御できるのも魅力です。

ちなみに、@import を使い CSS で Web フォントを読み込むのは、絶対におすすめできません。ものすごくサイト表示が遅くなります。