タイポグラフィは、優れたデザイン、ブランディング、読みやすさ、アクセシビリティの基本です。ウェブフォントを使用すると、上記のすべてを実現できます。テキストは選択、検索、ズームが可能で、高 DPI に対応しています。そのため、画面サイズや解像度に関係なく、一貫性のある鮮明なテキスト レンダリングを実現できます。WebFonts は、優れたデザイン、UX、パフォーマンスに欠かせません。
ウェブフォントの最適化は、全体的なパフォーマンス戦略の重要な要素です。各フォントは追加のリソースであり、一部のフォントはテキストのレンダリングをブロックすることがありますが、ページで WebFonts を使用しているからといって、レンダリングが遅くなるわけではありません。逆に、最適化されたフォントと、ページ上での読み込み方法と適用方法を適切に組み合わせることで、ページの合計サイズを小さくし、ページのレンダリング時間を短縮できます。
ウェブフォントの構造
ウェブフォントはグリフの集合であり、各グリフは文字や記号を表すベクター図形です。そのため、特定のフォント ファイルのサイズは、各グリフのベクターパスの複雑さと特定のフォント内のグリフ数という 2 つの単純な変数によって決まります。たとえば、最も人気のあるウェブフォントの一つである Open Sans には、ラテン文字、ギリシャ文字、キリル文字を含む 897 のグリフが含まれています。
フォントを選択する際は、どの文字セットがサポートされているかを考慮することが重要です。ページ コンテンツを複数の言語にローカライズする必要がある場合は、一貫性のあるデザインとエクスペリエンスを提供できるフォントを使用する必要があります。たとえば、Google の Noto フォント ファミリーは、世界中のすべての言語をサポートすることを目的としています。ただし、すべての言語を含む Noto の合計サイズの場合、ダウンロードされる ZIP のサイズは 1.1 GB 以上になります。
この投稿では、配信するウェブフォントのファイルサイズを小さくする方法について説明します。
ウェブフォント形式
現在、ウェブでは、次の 2 つの推奨フォント コンテナ形式があります。
WOFF と WOFF 2.0 は幅広くサポートされており、最新のすべてのブラウザでサポートされています。
- 最新のブラウザには WOFF 2.0 バリアントを提供します。
- Internet Explorer 11 のサポートなど、どうしても必要な場合は、WOFF をフォールバックとして使用します。
- あるいは、従来のブラウザではウェブフォントを使用せず、システム フォントを使用することをおすすめします。これは、制約のある古いデバイスでもパフォーマンスが向上する場合があります。
- WOFF と WOFF 2.0 は、現在も使用されている最新および従来のブラウザのすべてのベースに対応しているため、EOT と TTF を使用する必要がなくなり、ウェブフォントのダウンロード時間が長くなる可能性があります。
ウェブフォントと圧縮
WOFF と WOFF 2.0 はどちらも圧縮機能が組み込まれています。WOFF 2.0 の内部圧縮には Brotli が使用されており、WOFF よりも最大 30% 優れた圧縮を実現します。詳しくは、WOFF 2.0 評価レポートをご覧ください。
最後に、一部のフォント形式には、フォント ヒンティングやカーニング情報などの追加のメタデータが含まれており、プラットフォームによっては不要な場合があります。これにより、ファイルサイズをさらに最適化できます。たとえば Google Fonts では、フォントごとに 30 以上の最適化されたバリエーションが維持され、各プラットフォームとブラウザに最適なバリエーションを自動的に検出して配信しています。
@font-face
でフォント ファミリーを定義する
@font-face
CSS アットルールを使用すると、特定のフォント リソースの場所、スタイル特性、使用する Unicode コードポイントを定義できます。このような @font-face
宣言を組み合わせて使用すると、「フォント ファミリー」、ブラウザはこれを使用して、現在のページに適用する必要があるフォント リソースを評価します。
可変フォントを検討する
可変フォントを使用すると、フォントの複数のバリエーションが必要な場合に、フォントのファイルサイズを大幅に縮小できます。通常のスタイルと太字のスタイル、その斜体バージョンを読み込む代わりに、すべての情報を含む 1 つのファイルを読み込むことができます。ただし、可変フォント ファイルのサイズは、個々のフォント バリエーションより大きくなりますが、多数のバリエーションを組み合わせる場合より小さくなります。1 つの大きな可変フォントよりも、重要なフォント バリエーションを最初に配信し、他のバリエーションは後でダウンロードすることをおすすめします。
可変フォントは、最新のすべてのブラウザでサポートされるようになりました。詳しくは、ウェブ上の可変フォントの概要をご覧ください。
適切な形式を選択する
各 @font-face
宣言では、フォント ファミリーの名前(複数の宣言の論理グループとして機能)、フォント プロパティ(スタイル、ウェイト、ストレッチなど)と、src 記述子(フォント リソースの場所の優先順位付きリスト)を指定します。
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome.woff2') format('woff2'),
/* Only serve WOFF if necessary. Otherwise,
WOFF 2.0 is fine by itself. */
url('/fonts/awesome.woff') format('woff');
}
@font-face {
font-family: 'Awesome Font';
font-style: italic;
font-weight: 400;
src: local('Awesome Font Italic'),
url('/fonts/awesome-i.woff2') format('woff2'),
url('/fonts/awesome-i.woff') format('woff');
}
まず、上記の例では 1 つの Awesome Font ファミリーを定義し、2 つのスタイル(標準と斜体)をそれぞれ別のフォント リソース セットを指しています。また、各 src
記述子には、リソースのバリアントの優先順位付けされたカンマ区切りのリストが含まれます。
local()
ディレクティブを使用すると、ローカルにインストールされているフォントを参照、読み込み、使用できます。ユーザーがすでにフォントをシステムにインストールしている場合は、ネットワークを完全に経由せずに済み、最速の方法です。url()
ディレクティブを使用すると、外部フォントを読み込むことができます。また、オプションのformat()
ヒント(指定した URL で参照されるフォントの形式を示す)を含めることができます。
ブラウザはフォントが必要であると判断すると、指定されたリソースリストを指定された順序で処理し、適切なリソースを読み込もうとします。たとえば、上の例のようになります。
- ブラウザはページ レイアウトを実行し、ページ上の指定されたテキストをレンダリングするために必要なフォント バリアントを決定します。ページの CSS オブジェクト モデル(CSSOM)に含まれないフォントは、必須ではないためブラウザにはダウンロードされません。
- ブラウザは、必要なフォントごとに、フォントがローカルで使用できるかどうかを確認します。
- フォントがローカルで利用できない場合、ブラウザは外部定義を反復処理します。
<ph type="x-smartling-placeholder">
- </ph>
- 形式ヒントが存在する場合、ブラウザはダウンロードを開始する前に、ヒントがサポートされているかどうかをチェックします。ブラウザがヒントをサポートしていない場合、次のヒントに進みます。
- 形式ヒントが存在しない場合、ブラウザはリソースをダウンロードします。
ローカル ディレクティブと外部ディレクティブを適切なフォーマット ヒントと組み合わせることで、使用可能なフォント形式をすべて指定し、残りはブラウザに処理させることができます。ブラウザは、必要なリソースを判断して最適な形式を選択します。
Unicode 範囲のサブセット化
@font-face
ルールを使用すると、スタイル、太さ、ストレッチなどのフォント プロパティに加え、各リソースでサポートされる Unicode コードポイントのセットを定義できます。これにより、大きな Unicode フォントを小さなサブセット(ラテン文字、キリル文字、ギリシャ語など)に分割し、特定のページのテキストをレンダリングするために必要なグリフのみをダウンロードできるようになります。
unicode-range
記述子を使用すると、範囲値のカンマ区切りリストを 3 つの異なる形式のいずれかで指定できます。
- 単一のコードポイント(例:
U+416
) - 区間の範囲(例:
U+400-4ff
): 範囲の開始コードポイントと終了コードポイントを示します。 - ワイルドカードの範囲(例:
U+4??
):?
文字は任意の 16 進数を示します。
たとえば、Awesome Font ファミリーをラテン文字と日本語に分割できます。 それぞれが必要に応じてダウンロードされます。
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome-l.woff2') format('woff2');
/* Latin glyphs */
unicode-range: U+000-5FF;
}
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome-jp.woff2') format('woff2');
/* Japanese glyphs */
unicode-range: U+3000-9FFF, U+ff??;
}
Unicode 範囲のサブセットと、フォントのスタイルのバリエーションごとに個別のファイルを使用することで、ダウンロードを高速化し効率の高い複合フォント ファミリーを定義できます。サイト訪問者は必要なバリアントとサブセットのみをダウンロードし、そのページで決して使用されない可能性のあるサブセットをダウンロードする必要はありません。
ほぼすべてのブラウザが unicode-range
をサポートしています。古いブラウザとの互換性を維持するため、「手動サブセット化」へのフォールバックが必要になる場合があります。この場合、必要なサブセットをすべて含む単一のフォント リソースを提供するようフォールバックし、残りはブラウザで非表示にする必要があります。たとえば、ラテン文字のみを使用しているページでは、他のグリフを取り除いて、特定のサブセットをスタンドアロン リソースとして提供できます。
- どのサブセットが必要かを判断する:
<ph type="x-smartling-placeholder">
- </ph>
- ブラウザで Unicode 範囲のサブセット化がサポートされている場合は、適切なサブセットが自動的に選択されます。このページでは、サブセット ファイルを提供し、
@font-face
ルールで適切な Unicode 範囲を指定するだけで済みます。 - ブラウザで unicode-range によるサブセット化がサポートされていない場合は、不要なサブセットをすべて非表示にする必要があります。つまり、デベロッパーは必要なサブセットを指定する必要があります。
- ブラウザで Unicode 範囲のサブセット化がサポートされている場合は、適切なサブセットが自動的に選択されます。このページでは、サブセット ファイルを提供し、
- フォント サブセットを生成します。
<ph type="x-smartling-placeholder">
- </ph>
- オープンソースの pyftsubset ツールを使用して、フォントのサブセット化と最適化を行います。
- Google Font などの一部のフォント サーバーでは、デフォルトで自動的にサブセットが使用されます。
- 一部のフォント サービスでは、カスタムクエリ パラメータを使用して手動でサブセット化し、ページに必要なサブセットを手動で指定できます。詳しくは、フォント プロバイダのドキュメントをご覧ください。
フォントの選択と統合
各フォント ファミリーは、複数のスタイルのバリエーション(標準、太字、斜体)と各スタイル用の複数の太さで構成できます。その各要素には、大きく異なるグリフ形状(スペースやサイズが異なる、まったく異なる形状など)が含まれていることがあります。
上の図は、太字の太さが 3 種類のフォント ファミリーを示しています。
- 400(レギュラー)。
- 700(太字)。
- 900(非常に太字)。
中間のパターン(グレーで表示)はすべて、ブラウザによって自動的に最も近いパターンにマッピングされます。
指定されたウェイトに対応するフェイスが存在しない場合は、それに近いウェイトのフェイスが使用されます。一般に、太字のウェイトはより重いウェイトのフェイスにマッピングされ、軽量のフェイスはより軽いウェイトのフェイスにマッピングされます。
<ph type="x-smartling-placeholder"></ph> CSS フォント マッチング アルゴリズム をご覧ください。
斜体のバリアントにも同様のロジックが適用されます。フォント デザイナーは、どのパターンを生成するかを制御し、どのパターンをページで使用するかを制御します。各バリエーションは個別にダウンロードされるため、バリエーションの数は少なくしておくことをおすすめします。たとえば、Awesome Font ファミリーに太字のバリエーションを 2 つ定義できます。
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome-l.woff2') format('woff2');
/* Latin glyphs */
unicode-range: U+000-5FF;
}
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 700;
src: local('Awesome Font'),
url('/fonts/awesome-l-700.woff2') format('woff2');
/* Latin glyphs */
unicode-range: U+000-5FF;
}
上記の例では、Awesome Font ファミリーを宣言しています。このファミリーは、ラテングリフの同じセット(U+000-5FF
)に対応し、標準(400)と太字(700)の 2 つの異なる「太さ」を提供します。しかし、いずれかの CSS ルールで異なるフォントの太さを指定した場合や、font-style
プロパティが italic
に設定されている場合はどうなりますか。
- 完全一致のフォントを利用できない場合、ブラウザは最も近いフォントを使用します。
- スタイルに一致するフォントが見つからなかった場合(たとえば、上記の例で斜体のバリエーションが宣言されていない場合)、ブラウザは独自のフォント バリエーションを合成します。
上記の例は、Open Sans の実際のフォントと合成フォントの結果の違いを示しています。合成されたすべてのバリエーションは、1 つの 400 ウェイトのフォントから生成されます。ご覧のように、結果には顕著な違いがあります。太字と斜体のバリエーションの生成方法の詳細は指定されていません。そのため、結果はブラウザごとに異なり、フォントにも大きく依存します。
ウェブのフォントサイズの最適化チェックリスト
- フォントの使用を監査、監視する: ページ上でフォントを多用しすぎないようにし、フォントごとに使用するバリエーションの数を最小限に抑えます。これにより、一貫性のある高速なユーザー エクスペリエンスを実現できます。
- 可能であれば以前の形式を使用しない: EOT、TTF、WOFF の各形式は WOFF 2.0 よりも大きくなります。EOT と TTF はまったく不要な形式ですが、Internet Explorer 11 をサポートする必要がある場合は WOFF を使用できる場合があります。最新のブラウザのみをターゲットとする場合は、WOFF 2.0 のみを使用するのが、最もシンプルでパフォーマンスの高いオプションです。
- フォント リソースのサブセット化: 多くのフォントをサブセット化したり、複数の Unicode 範囲に分割したりして、特定のページに必要なグリフのみを提供できます。これにより、ファイルサイズが小さくなり、リソースのダウンロード速度が向上します。ただし、サブセットを定義するときは、フォントの再利用のために注意深く最適化してください。たとえば、各ページで異なる文字セットをダウンロードし、重複してはいけません。 スクリプト(ラテン文字やキリル文字など)に基づいてサブセットを作成することをおすすめします。
src
リスト内のlocal()
を優先する:src
リストの最初にlocal('Font Name')
を指定すると、インストール済みのフォントに対する HTTP リクエストが行われなくなります。- Lighthouse を使用して、テキスト圧縮をテストします。
Largest Contentful Paint(LCP)と Cumulative Layout Shift(CLS)への影響
ページのコンテンツによっては、テキストノードが Largest Contentful Paint(LCP)の候補となる場合があります。そのため、この記事のおすすめの方法に沿って、ウェブフォントをできる限り小さくして、ページ上のテキストができるだけ早くユーザーに表示されるようにすることが重要です。
ウェブフォント リソースのサイズが大きいために、最適化を行ってもページテキストの表示に時間がかかりすぎることが懸念される場合は、font-display
プロパティにさまざまな設定を行って、フォントのダウンロード中に非表示テキストが発生しないようにしてください。ただし、swap
値を使用するとレイアウトが大幅にシフトし、サイトの Cumulative Layout Shift(CLS)に影響を与える可能性があります。可能であれば、optional
または fallback
値の使用を検討してください。
ウェブフォントがブランディング、ひいてはユーザー エクスペリエンスにとって重要である場合は、フォントをプリロードして、ブラウザですぐにリクエストできるようにすることを検討してください。これにより、スワップ期間(font-display: swap
を使用している場合)とブロック期間(font-display
を使用していない場合)の両方を短縮できます。