フォントに関するおすすめの方法

Core Web Vitals のウェブフォントを最適化します。

この記事では、フォントのパフォーマンスに関するベスト プラクティスについて説明します。ウェブフォントがパフォーマンスに与える影響は、以下のようにさまざまです。

  • テキスト レンダリングの遅延: ウェブフォントが読み込まれていない場合、通常はブラウザでテキスト レンダリングが遅延します。多くの場合、これにより First Contentful Paint(FCP)の遅延が発生します。これにより、Largest Contentful Paint(LCP)が遅延することがあります。
  • レイアウト シフト: フォント スワップを行うと、レイアウト シフトが発生する可能性があるため、Cumulative Layout Shift(CLS)に影響を与える可能性があります。このようなレイアウト シフトは、ウェブフォントとその代替フォントがページ上で占めるスペースが異なる場合に発生します。

この記事は、フォントの読み込みフォント配信フォントのレンダリングの 3 つのセクションに分かれています。各セクションでは、フォント ライフサイクルの特定の要素がどのように機能するかを説明し、対応するベスト プラクティスを紹介します。

フォントを読み込んでいます

一般的に、フォントは重要なリソースです。フォントがないと、ユーザーはページ コンテンツを表示できません。したがって、一般的に、フォントの読み込みに関するベスト プラクティスは、できる限り早くフォントを読み込むように重点を置いています。サードパーティのサイトから読み込むフォント ファイルをダウンロードするには、個別の接続設定が必要になるため、特に注意が必要です。

ページのフォントが期間内にリクエストされているかどうかわからない場合は、Chrome DevTools の [ネットワーク] パネル内の [タイミング] タブで詳細をご確認ください。

DevTools の [Timing] タブのスクリーンショット

@font-face について

フォント読み込みのベスト プラクティスを詳しく見ていく前に、@font-face の仕組みと、それがフォントの読み込みに及ぼす影響を理解しておくことが重要です。

@font-face 宣言は、ウェブフォントを使用するうえで不可欠な要素です。少なくとも、フォントの参照に使用する名前を宣言し、対応するフォント ファイルの場所を示します。

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

よくある誤解は、@font-face 宣言が検出されたときにフォントがリクエストされるというものですが、これは当てはまりません。@font-face の宣言だけでは、フォントのダウンロードがトリガーされません。ページで使用されているスタイルで参照されている場合にのみ、フォントがダウンロードされます。たとえば、次のように指定します。

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

h1 {
  font-family: "Open Sans"
}

つまり上記の例では、ページに <h1> 要素が含まれている場合にのみ Open Sans がダウンロードされます。

したがって、フォントの最適化について検討する際は、スタイルシートもフォント ファイルそのものと同様に考慮することが重要です。スタイルシートのコンテンツまたは配信を変更すると、フォントが表示されるタイミングに大きな影響を与える可能性があります。同様に、使用していない CSS や分割されたスタイルシートを削除すると、ページで読み込まれるフォントの数を減らすことができます。

インライン フォント宣言

ほとんどのサイトでは、フォント宣言やその他の重要なスタイルを外部スタイルシートに含めるよりも、メイン ドキュメントの <head> でインライン化する方が大きなメリットを得られます。これにより、ブラウザで外部スタイルシートのダウンロードを待つ必要がなくなるため、ブラウザでフォント宣言をより早く検出できるようになります。

<head>
  <style>
    @font-face {
        font-family: "Open Sans";
        src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    }

    body {
        font-family: "Open Sans";
    }

    ...etc.

  </style>
</head>

重要な CSS のインライン化はより高度な手法になり得ますが、すべてのサイトで実現できるとは限りません。パフォーマンス上のメリットは明白ですが、必要な CSS(理想的には重要な CSS のみ)が正しくインライン化され、追加の CSS がレンダリング ブロックされていない方法で配信されるようにするには、追加のプロセスとビルドツールが必要です。

重要なサードパーティの送信元に事前接続する

サイトがサードパーティのサイトからフォントを読み込む場合は、preconnect リソースヒントを使用して、サードパーティのオリジンとの早期の接続を確立することを強くおすすめします。リソースヒントは、ドキュメントの <head> に配置する必要があります。以下のリソースヒントは、フォント スタイルシートを読み込むための接続を設定します。

<head>
  <link rel="preconnect" href="https://fonts.com">
</head>

フォント ファイルのダウンロードに使用する接続を事前に接続するには、crossorigin 属性を使用する preconnect リソースヒントを別途追加します。スタイルシートとは異なり、フォント ファイルは CORS 経由で送信する必要があります。

<head>
  <link rel="preconnect" href="https://fonts.com">
  <link rel="preconnect" href="https://fonts.com" crossorigin>
</head>

preconnect リソースヒントを使用する場合、フォント プロバイダが別々の生成元からスタイルシートとフォントを提供する可能性があることに留意してください。たとえば、Google Fonts で preconnect リソースヒントがどのように使用されるかを示します。

<head>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
</head>

preload を使用してフォントを読み込むときは注意する

preload は、ページ読み込みプロセスの早い段階でフォントを検出可能にするのに非常に効果的ですが、その代償としてブラウザ リソースを他のリソースの読み込みから消費することになります。

フォント宣言をインライン化し、スタイルシートを調整する方が効果的な場合もあります。こうした調整は、単に回避策を提供するのではなく、遅れて検出されるフォントの根本原因への対応に近づくものです。

また、フォント読み込み戦略として preload を使用する場合は、ブラウザに組み込まれているコンテンツ交渉戦略の一部が省略されるため、慎重に使用する必要があります。たとえば、preload では unicode-range 宣言が無視されるため、慎重に使用する場合は、1 つのフォント形式を読み込む場合にのみ使用してください。

ただし、外部スタイルシートを使用する場合、ブラウザはかなり後になるまでフォントが必要かどうかを検出できないため、最も重要なフォントをプリロードすると非常に効果的です。

フォント配信

フォント配信が高速化され、テキストのレンダリングが高速化されます。また、フォントを早めに配信することで、フォントの入れ替えによるレイアウト シフトをなくすことができます。

自己ホスト型フォントの使用

紙面では、自己ホスト型フォントを使用するとサードパーティとの接続設定が不要になるため、パフォーマンスが向上します。ただし、実際にはこれら 2 つのオプションのパフォーマンスの違いはそれほど明確ではありません。たとえば、Web Almanac では、サードパーティのフォントを使用しているサイトのほうが、ファースト パーティのフォントを使用したフォントよりもレンダリングが速いことがわかりました。

自己ホスト型フォントの使用を検討している場合は、サイトでコンテンツ配信ネットワーク(CDN)HTTP/2 を使用していることをご確認ください。これらのテクノロジーを使用しなければ、自己ホスト型のフォントでパフォーマンスが向上する可能性は低くなります。詳しくは、コンテンツ配信ネットワークをご覧ください。

自己ホスト型フォントを使用する場合は、通常、サードパーティのフォント プロバイダが自動的に提供するフォント ファイルの最適化(フォントのサブセット化や WOFF2 圧縮など)を適用することをおすすめします。こうした最適化を適用するために必要な作業量は、サイトでサポートされている言語によって若干異なります。特に、CJK 言語のフォントの最適化は特に困難な場合があります。

WOFF2 を使用する

最新のフォント フォントの中でも WOFF2 は最新で、ブラウザ サポートの幅が広く、圧縮率も最も優れています。Brotli を使用しているため、WOFF2 は WOFF よりも圧縮率が 30% 向上し、ダウンロードするデータが少なくなり、パフォーマンスが向上します。

ブラウザがサポートされていることから、専門家は現在、WOFF2 のみを使用することを推奨しています。

実際、私たちは今こそ、WOFF2 のみを使用し、他のものは無視すべきだと考えているときが来たと考えています。

これにより、CSS とワークフローが大幅に簡素化され、フォントが誤って二重または誤ってダウンロードされるのを防ぐことができます。WOFF2 がどこでもサポートされるようになりました。そのため、本当に古いブラウザをサポートする必要がない限り、WOFF2 を使用してください。それができない場合は、古いブラウザにはウェブフォントをまったく配信しないことを検討してください。堅牢なフォールバック戦略を導入していれば、これは問題にはなりません。古いブラウザを使用しているユーザーには代替フォントが表示されます。

<ph type="x-smartling-placeholder"></ph> Bram Stein(2022 Web Almanac より) をご覧ください。

サブセット フォント

通常、フォント ファイルには、サポートするさまざまな文字のすべてに対応する多数のグリフが含まれています。ただし、ページのすべての文字が必要というわけではなく、フォントのサブセット化によってフォント ファイルのサイズを小さくすることもできます。

@font-face 宣言の unicode-range 記述子は、フォントを使用できる文字をブラウザに通知します。

@font-face {
    font-family: "Open Sans";
    src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    unicode-range: U+0025-00FF;
}

Unicode 範囲に一致する文字がページに 1 つ以上含まれている場合、フォント ファイルがダウンロードされます。unicode-range は通常、ページ コンテンツで使用されている言語に応じて異なるフォント ファイルを提供するために使用されます。

unicode-range は多くの場合、サブセット化の手法と組み合わせて使用されます。サブセット フォントには、元のフォント ファイルに含まれていたグリフのごく一部が含まれます。たとえば、すべての文字をすべてのユーザーに配信するのではなく、ラテン文字とキリル文字のそれぞれについて、フォントのサブセットをそれぞれ生成するサイトもあります。フォントごとのグリフの数はさまざまです。ラテン フォントは通常、フォントあたり 100 から 1,000 のグリフです。CJK フォントの場合は 10,000 文字を超えることがあります。使用していないグリフを削除すると、フォントのファイルサイズを大幅に縮小できます。

フォント プロバイダによっては、フォント ファイルのさまざまなバージョンとサブセットが自動的に提供されることがあります。たとえば、Google Fonts はデフォルトでこれを行います。

/* devanagari */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJbecnFHGPezSQ.woff2) format('woff2');
  unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJnecnFHGPezSQ.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

自己ホスティングに移行する場合、この最適化は見落とされがちで、ローカルでフォント ファイルが大きくなります。

フォント プロバイダが許可している場合は、API を使用するか(Google Fonts がtextパラメータを提供することでサポートします)、またはフォント ファイルを手動で編集してから自己ホスティングを行って、フォントを手動でサブセット化することもできます。フォント サブセットを生成するツールには、subfontglyphanger などがあります。ただし、使用するフォントのライセンスを確認して、サブセット化と自己ホスティングを許可してください。

ウェブフォントの使用を減らす

最速のフォントは、そもそもリクエストされていないフォントです。システム フォントと可変フォントの 2 つは、サイトで使用するウェブフォントの数を減らすための方法です。

システム フォントは、ユーザーのデバイスのユーザー インターフェースで使用されるデフォルトのフォントです。通常、システム フォントはオペレーティング システムやバージョンによって異なります。フォントはすでにインストールされているため、ダウンロードする必要はありません。システム フォントは本文テキストに特に適しています。

CSS でシステム フォントを使用するには、フォント ファミリーとして system-ui を指定します。

font-family: system-ui

可変フォントの背後にある考え方は、1 つの可変フォントを複数のフォント ファイルの代わりに使用できるということです。可変フォントを使用するには、「デフォルト」のフォント スタイルを指定し、フォントを操作するための "ax" を指定します。たとえば、Weight 軸の可変フォントを使用すると、これまでは、ライト、レギュラー、太字、極太に別々のフォントが必要だったレタリングを実装できます。

可変フォントに切り替えることで、すべてのユーザーがメリットを得られるわけではありません。可変フォントには多くのスタイルが含まれているため、通常は、スタイルが 1 つしか含まれていない非可変フォントの個別のファイルよりもファイルサイズが小さくなります。可変フォントの使用による改善が最も大きいサイトは、さまざまなフォントのスタイルや太さを使用している(使用する必要がある)サイトです。

フォントのレンダリング

ウェブフォントがまだ読み込まれていないと、ブラウザはジレンマに直面します。ウェブフォントが表示されるまで、テキストのレンダリングを保留にすべきでしょうか。それとも、ウェブフォントが届くまでは代替フォントでテキストをレンダリングすべきでしょうか?

このシナリオの処理はブラウザによって異なります。デフォルトでは、Chromium ベースと Firefox のブラウザは、関連するウェブフォントが読み込まれていない場合、テキスト レンダリングを最大 3 秒間ブロックします。Safari はテキストのレンダリングを無期限にブロックします。

この動作は、font-display 属性を使用して構成できます。この選択は、重大な影響を及ぼす可能性があります。font-display は、LCP、FCP、レイアウトの安定性に影響する可能性があります。

適切な font-display 戦略を選択する

font-display は、関連するウェブフォントが読み込まれていない場合に、テキスト レンダリングをどのように進めるかをブラウザに通知します。フォントフェースごとに定義されます。

@font-face {
  font-family: Roboto, Sans-Serif
  src: url(/fonts/roboto.woff) format('woff'),
  font-display: swap;
}

font-display には 5 つの値があります。

ブロック期間 入れ替え期間
自動 ブラウザによって異なる ブラウザによって異なる
ブロック 2 ~ 3 秒 無限
スワップ 0 ミリ秒 無限
フォールバック 100ms 3 秒
省略可 100ms なし
  • ブロック期間: ブロック期間は、ブラウザがウェブフォントをリクエストしたときから始まります。ブロック期間中、ウェブフォントが使用できない場合、フォントは非表示の代替フォントでレンダリングされるため、テキストはユーザーに表示されません。ブロック期間の終了時にフォントが使用できない場合、フォントは代替フォントでレンダリングされます。
  • スワップ期間: スワップ期間はブロック期間の後になります。スワップ期間中にウェブフォントが使用可能になると、フォントが「スワップ」されます。できます。

font-display 戦略は、パフォーマンスと美観のトレードオフに関して、さまざまな視点を反映しています。このように、個々の好み、ページやブランドにとってウェブフォントがどの程度重要か、また、入ってくるのが遅かったフォントをスワップインしたときにどの程度不快感を与えるかによって異なるため、おすすめのアプローチを提示することは困難です。

ほとんどのサイトでは、次の 3 つの戦略が最も有効です。

  • パフォーマンスが最優先事項の場合: font-display: optional を使用します。これは最も「パフォーマンスが高い」アプローチ: テキスト レンダリングの遅延が 100 ミリ秒以下で、フォントの入れ替えに関連するレイアウト シフトがないことが保証されます。ただし、ウェブフォントの到着が遅れると、フォントが使用されないというデメリットがあります。

  • テキストをすばやく表示することが最優先事項であるものの、ウェブフォントを確実に使用したい場合: font-display: swap を使用しますが、レイアウト シフトが発生しないように早めにフォントを配信してください。このオプションの欠点は、フォントの到着が遅くなると移動が不快になることです。

  • テキストがウェブフォントで表示されるようにすることが最優先事項の場合: font-display: block を使用しますが、テキストの遅延を最小限に抑えるために、早い段階でフォントを配信してください。このデメリットは、最初のテキスト表示が遅れることです。このように再生されていても、テキストが実際には非表示として描画されるため、レイアウト シフトが発生する可能性があります。その場合、代替のフォント スペースがスペースの予約に使用されます。ウェブフォントが読み込まれた後に、差分のスペースが必要になり、結果が変わる可能性があります。ただし、これは、テキスト自体がシフトしたとは認識されないため、font-display: swap よりも不快感が少なくなる可能性があります。

で確認できます。

また、この 2 つのアプローチを組み合わせることもできます。たとえば、ブランディングなどの視覚的に特徴的なページ要素には font-display: swap を使用します。本文で使用するフォントには font-display: optional を使用します。

代替フォントとウェブフォントのずれを減らす

CLS の影響を軽減するには、新しい size-adjust 属性を使用します。詳しくは、CSS size-adjust に関する記事をご覧ください。これは Google のツールセットに新たに追加された機能であるため、より高度で、現在はやや手動です。ただし、必ずテストして、今後のツールの改善を見守ってください。

まとめ

ウェブフォントは依然としてパフォーマンスのボトルネックですが、ウェブフォントを最適化して可能な限りこのボトルネックを軽減できる選択肢は広がり続けています。