ウェブのフォントサイズを縮小する

タイポグラフィは、優れたデザイン、ブランディング、読みやすさ、アクセシビリティの基本です。ウェブフォントを使用すると、上記のすべてを実現できます。テキストは選択可能、検索可能、ズーム可能で、高 DPI に対応しており、画面サイズや解像度に関係なく、一貫して鮮明なテキスト レンダリングを実現します。ウェブフォントは、優れたデザイン、UX、パフォーマンスに不可欠です。

ウェブフォントの最適化は、全体的なパフォーマンス戦略の重要な要素です。各フォントは追加のリソースであり、フォントによってはテキストのレンダリングがブロックされる可能性がありますが、ページでウェブフォントを使用しているからといって、レンダリングが遅くなるわけではありません。最適化されたフォントと、ページでの読み込みと適用方法に関する適切な戦略を組み合わせることで、ページ全体のサイズを削減し、ページ レンダリング時間を短縮できます。

ウェブフォントの構造

ウェブフォント はグリフのコレクションであり、各グリフは文字や記号を表すベクター図形です。そのため、特定のフォント ファイルのサイズは、各グリフのベクターパスの複雑さと、特定のフォントのグリフの数という 2 つの単純な変数によって決まります。たとえば、最も人気のあるウェブフォントの 1 つである Open Sans には、ラテン文字、ギリシャ文字、キリル文字を含む 897 個のグリフが含まれています。

フォント グリフテーブル

フォントを選択する際は、どの文字セットがサポートされているかを考慮することが重要です。ページ コンテンツを複数の言語にローカライズする必要がある場合は、ユーザーに一貫したルック&フィールを提供できるフォントを使用する必要があります。たとえば、Google の Noto フォント ファミリーは、世界中のすべての言語をサポートすることを目指しています。ただし、すべての言語を含む Noto の合計サイズは 1.1 GB を超える ZIP ダウンロードになります。

この記事では、配信されるウェブフォントのファイルサイズを削減する方法について説明します。

ウェブフォントの形式

現在、ウェブで使用されている推奨フォント コンテナ形式は 2 つあります。

WOFFWOFF 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');
}

まず、上記の例では、2 つのスタイル(標準と斜体)を持つ 1 つのAwesome Fontファミリーが定義されており、それぞれが異なるフォント リソースのセットを指しています。各 src 記述子には、優先順位付きのカンマ区切りのリソース バリアントのリストが含まれています。

  • local() ディレクティブを使用すると、ローカルにインストールされているフォントを参照、読み込み、使用できます。ユーザーのシステムにフォントがすでにインストールされている場合、ネットワークを完全にバイパスするため、最も高速です。
  • url() ディレクティブを使用すると、外部フォントを読み込むことができます。また、指定された URL で参照されるフォントの形式を示すオプションの format() ヒントを含めることができます。

ブラウザは、フォントが必要であると判断すると、指定された順序で指定されたリソースリストを反復処理し、適切なリソースを読み込もうとします。たとえば、上記の例では次のようになります。

  1. ブラウザはページ レイアウトを実行し、ページに指定されたテキストをレンダリングするために必要なフォント バリアントを特定します。ページの CSS オブジェクト モデル(CSSOM)の一部ではないフォントは、必要ないためブラウザによってダウンロードされません。
  2. 必要なフォントごとに、ブラウザはフォントがローカルで利用可能かどうかを確認します。
  3. フォントがローカルで利用できない場合、ブラウザは外部定義を反復処理します。
    • 形式のヒントが存在する場合、ブラウザはダウンロードを開始する前に、そのヒントをサポートしているかどうかを確認します。ブラウザがヒントをサポートしていない場合、ブラウザは次のヒントに進みます。
    • 形式のヒントがない場合、ブラウザはリソースをダウンロードします。

ローカル ディレクティブと外部ディレクティブを適切な形式のヒントと組み合わせることで、利用可能なすべてのフォント形式を指定し、残りの処理をブラウザに任せることができます。ブラウザは必要なリソースを特定し、最適な形式を選択します。

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しています。古いブラウザとの互換性を確保するには、「手動サブセット化」にフォールバックする必要がある場合があります。この場合、必要なすべてのサブセットを含む単一のフォント リソースを提供し、残りのサブセットをブラウザから非表示にする必要があります。たとえば、ページでラテン文字のみを使用している場合は、他のグリフを削除し、その特定のサブセットをスタンドアロン リソースとして提供できます。

  1. 必要なサブセットを特定する:
    • ブラウザが Unicode 範囲のサブセット化をサポートしている場合、適切なサブセットが自動的に選択されます。ページでは、サブセット ファイルを提供し、@font-face ルールで適切な Unicode 範囲を指定するだけです。
    • ブラウザが Unicode 範囲のサブセット化をサポートしていない場合、ページは不要なサブセットをすべて非表示にする必要があります。つまり、デベロッパーが必要なサブセットを指定する必要があります。
  2. フォント サブセットを生成する:
    • オープンソースの pyftsubset ツールを使用して、フォントをサブセット化して最適化します。
    • Google Font などの一部のフォント サーバーでは、デフォルトで自動的にサブセット化されます。
    • 一部のフォント サービスでは、カスタム クエリ パラメータを使用して手動でサブセット化できます。これを使用して、ページに必要なサブセットを手動で指定できます。フォント プロバイダのドキュメントをご覧ください。

フォントの選択と合成

各フォント ファミリーは、複数のスタイル バリアント(標準、太字、斜体)と、各スタイルの複数の太さで構成できます。それぞれに、間隔やサイズが異なる、またはまったく異なるグリフ形状が含まれている場合があります。

フォントの太さ

上の図は、3 つの異なる太字を提供するフォント ファミリーを示しています。

  • 400(標準)。
  • 700(太字)。
  • 900(超太字)。

その他の中間のバリアント(グレーで示されています)は、ブラウザによって最も近いバリアントに自動的にマッピングされます。

フェイスが存在しない太さが指定された場合は、太さが近いフェイスが使用されます。一般に、太字は太いフェイスにマッピングされ、細字は細いフェイスにマッピングされます。

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;
}

上記の例では、同じラテン文字グリフのセット(U+000-5FF)をカバーする 2 つのリソースで構成される Awesome Font ファミリーが宣言されていますが、標準(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 範囲に分割して、特定のページに必要なグリフのみを配信できます。これにより、ファイルサイズが削減され、リソースのダウンロード速度が向上します。ただし、サブセットを定義する際は、フォントの再利用を最適化するように注意してください。たとえば、ページごとに異なるが重複する文字セットをダウンロードしないでください。スクリプト(ラテン文字、キリル文字など)に基づいてサブセット化することをおすすめします。
  • local()src リストで優先する: 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 を使用しない場合はブロック期間を短縮できます。