Webフォントのサブセット化:CJKフォントの容量とfont-displayの実務的判断
日本語Webフォントは数千から数万の字形を含み、そのままでは数MBに達する。サブセット化と font-display の選択は避けられないが、CJKでは使う文字が事前に読めないため、ラテン文字とは異なる判断が要る。
日本語のWebフォントを自前で配信しようとすると、まず容量の壁に突き当たる。ラテン文字のフォントが数十KBで収まるのに対し、日本語フォントは数千から数万の字形を含み、そのままでは数MBに達する。サブセット化と font-display の選択は避けて通れない。ここでは、CJKフォント特有の判断を実装の観点から整理する。web.devやMDNのフォント最適化の資料も、この二点を基本に据えている。
CJKフォントはなぜ重いのか
重さの原因は単純で、字形の数だ。ラテン文字は基本ラテンと記号を合わせても数百字形に収まるが、日本語は常用漢字だけで二千字を超え、仮名・記号・全角英数を含めればさらに増える。字形一つひとつが輪郭データを持つため、総量がそのまま容量に跳ね返る。画像フォーマットの選択と同じく、ここでも「必要な分だけを送る」という発想が出発点になる。
サブセット化の考え方
サブセット化とは、実際に使う字形だけを抜き出して軽量なフォントを作る処理だ。ラテン文字なら「使う文字は事前に分かっている」ため単純だが、CJKでは事情が違う。ここで見落とされがちなのは、コンテンツに現れる漢字を事前に完全には読めないという点だ。記事本文が増えれば未知の漢字も増える。したがってCJKのサブセットは、既知のUI文字列に加えて、仮名・句読点・よく使う漢字を含む幅を持たせるか、あるいはコンテンツ確定後に再生成する運用が要る。unicode-range でブロックごとに分割配信すれば、ブラウザは必要な範囲だけを取得できる。ただし、分割を細かくしすぎるとリクエスト数が増え、かえって遅くなる。
font-displayの選択
font-display は、フォント読み込み中の表示方法を決める。swap はフォールバックを即表示し、あとでWebフォントに差し替えるが、この差し替えが文字の再レイアウトを起こし、レイアウトシフト(CLS)の原因になる。optional は、フォントがすぐ用意できなければその訪問では諦め、フォールバックのまま表示する。CLSを避けたいなら optional が有力だが、代償として、遅い回線ではWebフォントが一度も現れないことがある。つまりフォールバックの字面が単独で成立している必要がある。一方、本文の可読性を最優先し多少のシフトを許すなら swap も選択肢になる。
プリロードと読み込み順
どのフォントを選んでも、読み込みの優先順位は結果を左右する。ページの主要文字に使うフォントは <link rel="preload"> で早期に取得を始める。ただし、プリロードしたのに使われないと警告が出るため、@font-face のURLとプリロードのURLは一致させる必要がある。フォントの取得が本文の描画やヒーロー画像と競合する点は、WebGLシェーダーの実務的な検討で触れた読み込み競合と地続きだ。サブセット化した成果物の管理は、制作物のバージョン管理で扱う課題にもつながる。
容量・表示・読み込み順の三点
日本語Webフォントの最適化は、字形を絞る容量の問題、差し替えを制御する font-display の問題、優先度を決める読み込み順の問題に分かれる。ラテン文字の常識をそのまま持ち込むと、使う漢字が読めないという一点で崩れる。CJK特有の不確実性を前提に、幅を持たせたサブセットとCLSを避ける表示設定を選ぶことが、実務的な出発点になる。