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

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

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

ウェブフォントの構造

ウェブフォントはグリフの集まりであり、各グリフは文字や記号を表すベクター図形です。そのため、特定のフォント ファイルのサイズは、各グリフのベクターパスの複雑さと、特定のフォント内のグリフの数という 2 つの単純な変数によって決まります。たとえば、最も人気のある WebFonts の 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 でフォント ファミリーを定義する

CSS の @font-face ルールを使用すると、特定のフォント リソースの場所、スタイル特性、使用すべき 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 つのスタイル(normal と italic)のスタイルを設定しています。それぞれのスタイルは異なるフォント リソースのセットを指しています。次に、各 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;
}

上記の例では、Awesome Font ファミリーを宣言しています。このファミリーは、同じラテングリフ(U+000-5FF)のセットをカバーする 2 つのリソースで構成され、標準(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 を使用しない場合のブロック期間の両方を減らすことができます。