Google Fontsの日本語フォントの高速化施策が面白かった

本記事は【ウェブフォント Advent Calendar 2018】2日目参加記事です。

Web大好き人間、そして、フォント大好き人間の端くれとして参加させていただきました。よろしくお願いします。

Google Fontsで日本語フォントが正式リリース!

さて、今年のWebフォント界の大きなニュースといえば、やはりGoogle Fontsで日本語フォントが正式リリースされたことではないでしょうか。

これまでGoogle Fontsの日本語フォントはEarly Access(ベータ版)として2年くらい前からひっそりと配信されていましたが、ついに正式リリース!

これにより、日本語圏のWebフォントの導入や提案のハードルがグッと下がったように思います。

前置き:日本語フォントはファイルサイズが大きい、という話

Webフォントは その名の通りWebページで使えるフォントのことです。

しかし、日本語フォントは欧文(英語)フォントと比べてファイルサイズが大きく、読み込みに時間がかかってしまうという致命的な問題があります。

ファイルサイズが大きい理由は2つあります。

理由1:単純に文字が多い

欧文フォントの場合はアルファベットの大文字・小文字・数字・記号などを加えても数百程度で十分ですが、日本語はひらがなだけで90近くあります。

(五十音表を思い浮かべると50もないように感じますが、実際は濁点・半濁点・拗音などもあるためです。)

そしてカタカナもほぼ同じ数あり、漢字まで対応するとなると小学校で習う漢字だけで1000文字以上、常用漢字まで範囲を広げるとさらに1000文字以上……。

さらに「綾」「宏」「絆」などの常用外漢字にも対応するとなると、さらに数千字が必要になります。

理由2:漢字の字形が複雑

Webフォントに限らず、フォント業界はアウトラインフォントと呼ばれる輪郭線をデータ化した形式のフォントが主流です。

下の画像は「漢」と「A」のノード(輪郭線上の点)を表示したものです。漢字のほうがノードの量が多いのが分かるかと思います。

「漢」と「A」のパスを表示したもの
◆の部分が「ノード」と呼ばれる輪郭線上の点

アウトラインフォントは、ノードの量が多いほど(=字の形が複雑であればあるほど)データ量が増えます。

余談ですが、毛筆フォントなどは、同じ字でも筆のかすれなどの表現をするために非常に多くのノードを使っています。

「Noto Sans JP」と「KSO新豪龍」の比較
同じ「漢」でも、毛筆体のほうがノードが多い

フォントが重い=読み込みに時間がかかるのは致命的な問題!

このように、日本語フォントは文字の多さ・字形の複雑さの2つの要因で、フォントのサイズ(容量)が大きくなっています。

フォントのサイズが大きくなると、ページの読み込みに時間がかかってしまってなかなかテキストが表示されない問題が生じます。

余談ですが、サイト利用者が「ページが表示されるのを待てる時間」は年々短くなってきていて、ネットが普及し始めの頃は8秒程度でしたが今では3秒程度、一部では「1秒!」とまで言われています。

Webフォントを配信しているサービス側もそういった事情は把握していて、サブセット化(例:JavaScriptを用いて、ページ内で使われている文字のフォントだけを後出しで読み込ませる)などの対策をしています。

それではここから、Google Fontsの日本語フォントが一体どんな高速化対策をしているのか見ていきましょう。

本題:Google Fontsの日本語フォントの読み込み高速化施策

GoogleとAdobeが開発した「Noto Sans JP」を例に見てみましょう。

「Noto Sans JP」を読み込むタグはこちらです。

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

純粋にCSSを読み込んでいるようです。

そしてCSSの中身はこんな感じになっています!

/* [0] */
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  src: local('Noto Sans Japanese Regular'), local('NotoSansJapanese-Regular'), url(https://fonts.gstatic.com/s/notosansjp/v18/-F62fjtqLzI2JPCgQBnw7HFow2os2HUP5pp0erwTqsSGs8dLiZ-nVOFVLsE_RS1PblwsiBhLorUfH78.0.woff2) format('woff2');
  unicode-range: U+28946, U+28949, /*...(中略)...*/ U+2f9de-2f9df, U+2f9f4;
}
/* [1] */
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  src: local('Noto Sans Japanese Regular'), local('NotoSansJapanese-Regular'), url(https://fonts.gstatic.com/s/notosansjp/v18/-F62fjtqLzI2JPCgQBnw7HFow2os2HUP5pp0erwTqsSGs8dLiZ-nVOFVLsE_RS1PblwsiBhLorUfH78.1.woff2) format('woff2');
  unicode-range: U+243bc, U+243d0, /*...(中略)...*/ U+286d7, U+286fa;
}
/*...(中略)...*/
/* [119] */
@font-face {
  font-family: 'Noto Sans JP';
  font-style: normal;
  font-weight: 400;
  src: local('Noto Sans Japanese Regular'), local('NotoSansJapanese-Regular'), url(https://fonts.gstatic.com/s/notosansjp/v18/-F62fjtqLzI2JPCgQBnw7HFow2os2HUP5pp0erwTqsSGs8dLiZ-nVOFVLsE_RS1PblwsiBhLorUfH78.119.woff2) format('woff2');
  unicode-range: U+20, U+3001-3002, /*...(中略)...*/ U+ff0c, U+ff0e;
}

……むむっ?!

フォントの指定している @font-face が120個も並んでいます。

しかも全部、font-weight:400の「Noto Sans JP」です。

通常、1つのフォントを読み込む際は@font-face は1つで十分なはずですが…?

unicode-range でページの表示に必要なフォントファイルだけ読み込んでいた!

よく見ると、各 @font-faceunicode-range が指定されていますね。

これは、Unicodeコードポイント(文字に割り当てられた番地のようなもの)の範囲を表していて、

  • 指定してあるコードポイントの文字だけそのフォントで表示する
  • その文字が必要になったタイミングで自動で読み込む

という性質があります。

Google Fontsでは、フォントファイルを120個に分割して、ページ内のテキストの表示に必要なファイルだけ(※)読み込むことで高速化を実現しているというわけですね。

※例えば「書体」という2文字であれば、「書」を含むフォントファイルと「体」を含むフォントファイルのみ。

さらに、local(‘Noto Sans Japanese Regular’) という指定があるため、端末(ローカル)内に同名のフォントがあればそれを参照するようになっています。

余談:ただ単純に120個に分割しているわけじゃない?!

ちなみに、ただ単純に120個に分割したわけないじゃないみたいです!

日本語フォントが配信された際のプレスリリースにはこんなことが書かれていました。

参考 Google Fonts launches Japanese supportGoogle Design

この記事の前半では、日本語フォントが(文字の種類が多いため)ファイルサイズが大きなってしまう問題点を取り上げています。

そして注目すべきはこちらの一文。

Google Fonts’ innovative delivery system circumvents this problem by splitting the large fonts into roughly 100 “slices” based on an analysis of online language patterns.

日本語訳するとこんな感じです。

Google Fontsの革新的な配信システムでは、オンライン言語パターンの分析に基づきフォントをおよそ100の「スライス」に分割することにより、この問題を回避しています。

なんと、言語パターンを分析して文字を分割したそうです。

どのように分割しているのかチョット気になりなるところですが……それはまた次の機会で。

Google Fontsの日本語対応によって、これからWebの表現がより多彩になっていきそうですね!

それではまた!