Baseline CSS 機能を使用したレスポンシブで可変のタイポグラフィ

公開日: 2025 年 12 月 16 日

レスポンシブ ウェブ デザインとは、さまざまなブラウザ、ビューポートのサイズ、デバイス、ユーザー設定で適切に表示され、機能するウェブサイトを構築するためのアプローチです。タイポグラフィに適用する場合、主な懸念事項は、ブラウザの幅に基づいて font-size を調整することです。これは、line-heightmargin などのスペーシング値にも影響する可能性があります。

デザイナーは、ブラウザで利用できるスペースを考慮し、それに応じてタイポグラフィを調整する必要があります。また、ユーザーの状況はさまざまであり、デバイスのニーズも異なります。font-sizeそのため、最終結果に対するユーザーの制御を奪うようなことは危険です。ウェブの閲覧中にフォントサイズを変更するために使用できる主な入力方法は 2 つあります。

  • すべてのウェブサイトでデフォルトの font-size 設定を提供します。
  • サイトごとに拡大または縮小する。

このデモの目的は、ブラウザのビューポート サイズとユーザー入力の両方に対応したタイポグラフィを作成することです。ただし、タイポグラフィがビューポートに反応するほど、ユーザー設定への反応は小さくなることを理解しておくことが重要です。レスポンシブ タイポグラフィを実装する場合は、慎重に実装し、結果がアクセシブルであることをテストすることが重要です。

ユーザー設定に基づいてベース font-size をネゴシエートする

オンラインでタイポグラフィを定義する最初のステップは、ユーザーの font-size 設定に基づいて初期フォントサイズをネゴシエートすることです。これは、ページ上のテキストの大部分に使用され、見出しなどの他のフォントサイズの基準となります。ここで最も簡単な方法は、調整なしで 1em を使用してユーザーにフルコントロールを付与することです。他の font-size 値を設定していない場合、1em はユーザー設定を参照します。スペクトルの反対側では、ピクセルやその他の絶対単位(ビューポート相対単位も含む)で font-size を設定すると、ユーザーの設定が完全にオーバーライドされるため、避けるべきです。

ただし、ユースケースによって適切なタイポグラフィは異なります。記事は大きな文字で読みやすく、データ量の多いサイトは文字を小さくしてコンパクトなデザインにする必要があるかもしれません。いずれの場合も、ユーザーが独自の状況に合わせて結果を調整できるようにしながら、デザインに合ったデフォルトを提案することをおすすめします。

オプション 1: 推定に基づいて乗数を計算する

一般的な妥協案の 1 つは、ユーザーのデフォルトの font-size を基準として、調整された font-sizeem または % 単位で定義することです。一般的に、このアプローチは、ブラウザが 16px のデフォルトを提供し、ほとんどのユーザーがそのデフォルトをそのまま使用するという前提で始まります。サイトに 20px のフォントサイズが適していると思われる場合は、通常、font-size1.25em または 125% に設定すると、期待どおりの結果が得られます。

html {
  /* 20px preferred, 16px expected: 20/16 = 1.25 */
  font-size: 1.25em;
}

ここで calc() 関数を使用して計算を表示することもできますが、方程式(目標サイズを予想サイズで割り、1em を掛ける)を把握しておく必要があります。

html {
  font-size: calc(20 / 16 * 1em);
}

ユーザーの好みは結果に影響する可能性があります。デフォルトはユーザーの好みに相対的になるためです(この例では 1.25 倍)。ただし、あなたとユーザーの両方が 20px のデフォルトをリクエストし、結果が 25px(調整されたデフォルトの 1.25 倍)になった場合、誰もリクエストしていないサイズになるため、奇妙な結果になる可能性があります。

オプション 2: clamp() に処理を任せる

よりニュアンスのあるアプローチでは、数学を使わずに CSS 比較関数を使用します。1em が 16px と等しいと仮定して、px から em への信頼性の低い変換を行うのではなく、1em をユーザー設定を参照する変数と考えることができます。1em が表すピクセル値に関係なく、font-sizemax(1em, 20px) は常に、デザインの優先度(20px)とユーザーの優先度(1em)のうち大きい方を返します。これにより、ユーザーはフォントサイズを大きくすることはできますが、小さくすることはできません。

clamp() 関数に切り替えることで、ユーザーが希望するサイズが選択したデフォルトから大きく外れた場合に、両方向に拡大縮小できるようになります。たとえば、font-sizeclamp(1em, 20px, 1.25em) の場合、ユーザーのデフォルト値より大きく、デフォルト値の 125% 倍を超えない限り、デフォルト値は 20px になります。

これにより、ユーザー設定に近い場合はデザインが優先されますが、ユーザー設定が指定範囲外の場合はユーザー設定が優先されます。変換計算、ユーザー設定のサイズに関する仮定、デザイナーとユーザーの値の乗算は行われません。

これを html 要素のルート font-size として設定することで、ネゴシエーションされたベースサイズとして、サイトのどこからでも 1rem を参照できるようになりました。

レスポンシブ対応を追加する

この font-size をビューポートに対応させるには、メディアクエリ(またはコンテナクエリ)のブレークポイントを追加する方法があります。たとえば、画面サイズに応じてクランプされた値を変更できます。

html {
  font-size: clamp(1em, var(--base-font-size, 16px), 1.25em);
  @media (width > 30em) { --base-font-size: 18px; }
  @media (width > 45em) { --base-font-size: 20px; }
}

もう 1 つのオプションは、静的なベース値にビューポート単位またはコンテナ単位を追加することです。

html {
  font-size: clamp(1em, 16px + 0.25vw, 1.25em);
}

vw(ビューポートの幅)または vi(ビューポートのインライン サイズ)の単位は、ビューポート全体の 1%(サイトをレンダリングするブラウザの部分)を表します。同様に、cqw 単位と cqi 単位は、ページ上のインライン サイズ コンテナの 1% を表します。詳しくは、コンテナクエリと単位のデモをご覧ください。

このアプローチは、メディアまたはコンテナのブレークポイントで font-size の値が急に変わるのではなく、ビューポートの幅の範囲内で font-size の変化が一定であるため、流動的なタイポグラフィと呼ばれることがよくあります。ただし、移行の滑らかさに気を取られないでください。この違いは、ウィンドウ サイズをスムーズに調整した場合に、テストでのみ確認できるのが一般的です。この影響がユーザーに及ぶことはほとんどありません。ユーザーはブラウザのサイズやズームレベルを頻繁に変更する可能性がありますが、ブレークポイントとビューポート単位の違いに気づくには、ゆっくりとスムーズに調整する必要があります。これは、サイズ変更後の結果ではなく、切り替えにのみ影響します。

流動的なフォントサイズの主な利点は、ブレークポイントを手動で計算したり指定したりする必要がなくなり、任意のサイズで補間された結果が得られることです。開始点(16px)と変化率(0.25vw は、ビューポートの 100px の増加ごとに font-size0.25px の増加を提供します)のみを設定します。最小値と最大値も設定できます。ビューポートの幅が 1000px の場合、font-size16px + 2.5px または 18.5px になりますが、この計算はブラウザによって完全に処理されます。これは、コンテナベースのレスポンシブ性を示すために cqi 単位を使用するデモで使用されているアプローチです。コンテナが定義されていないルート(html)要素で使用される場合、cqi 単位は引き続きビューポート サイズを参照します。

特定のビューポート サイズで指定された font-size を基準に考える場合は、より直接的なメディアクエリ アプローチを使用することをおすすめします。この方が少しわかりやすいでしょう。意図したブレークポイントに基づいてビューポート単位を計算しようとすると、複雑になります。多くのユーザーは、サードパーティ製ツールから値をコピーして貼り付けることでこの作業を行っていますが、その結果として生成されるコードは、理解したり直接変更したりすることが非常に困難です。一般的に、CSS では、意図を最も明確に表現できるオプションが最適です。

警告: ビューポートの変更は常に同じ意味を持つとは限りません。

メディアクエリと vi 単位は異なる方法で適用されますが、どちらのアプローチもビューポートの同じ測定に基づいています。ビューポートの幅が 600px の場合、100vw600px と等しくなり、(width > 500px) メディアクエリ内のスタイルが適用されます。

ビューポートが 600px 幅であるとはどういう意味でしょうか?実際には、ピクセルはすべての状況で単一の意味を持つ固定サイズではありません。ピクセル数の少ないビューポートは、画面の小さいデバイス(スマートフォンなど)やブラウザの狭いウィンドウに表示されるのが自然ですが、これは信頼できる前提ではありません。実際、ブラウザ ウィンドウをズームインして小さくすると、測定されたビューポートの幅に同じ影響が及びます。一方のアクション(ズーム)はピクセルのサイズを変更し、もう一方のアクション(サイズ変更)はブラウザ自体のサイズを変更しますが、どちらもブラウザの幅にわたるピクセル数を変更します。ビューポートの測定から得られるのは、現在のピクセルサイズと現在のブラウザ ウィンドウの関係です。

ユーザーにとって、ズームとサイズ変更はそれぞれ異なる目的で使用されます。ズームレベルを変更するユーザーは、ページのコンテンツを拡大または縮小しようとしていますが、ブラウザのサイズを変更するユーザーは、さまざまな画面のスペースを管理しているだけです。ユーザーの意図は異なりますが、CSS 測定の結果は同じです。ウィンドウが小さくなるか、ピクセルが大きくなると、ブラウザの幅に収まるピクセル数が少なくなります。

この不一致により、レスポンシブ タイポグラフィの信頼性が低下します。テキストがビューポートまたはコンテナのみに基づいてサイズ変更されるように設定されている場合、ユーザーのズームは無効になります。

ビューポート相対単位の値を 1vw または 100vw に変更すると、フォントサイズとビューポートの正確な関係が変わります。1vw フォントはビューポート サイズの 100px ごとに 1px ずつ大きくなりますが、100vw フォントはビューポートとまったく同じサイズになります。この値を変更すると、ブラウザに対するフォントの拡大率を遅くしたり速くしたりできます。ただし、ビューポート相対値は、ユーザーがズームインまたはズームアウトしても一定のままになり、ユーザー コントロールにまったく反応しません。

同様に、1vw100vw もユーザーのデフォルト font-size を考慮しません。

font-size にビューポートまたはコンテナ相対単位を単独で使用することは、常にユーザーにとって有害です。font-size がコンテナに完全にレスポンシブである場合、ユーザーのデフォルトや調整にもレスポンシブにすることはできません。最善の意図と保護手段があっても、最終的な font-size 制御をユーザーから奪うことは避けるべきです。これはユーザー エクスペリエンスを損なうだけでなく、法律で義務付けられているアクセシビリティ ガイドラインに違反する可能性もあります。具体的には、ウェブ コンテンツ アクセシビリティ ガイドラインのセクション 1.4.4 で、「補助技術を使用せずにテキストのサイズを最大 200% まで変更できる」ことが求められています。

font-size 値がズームに対応するようにする方法

ビューポート相対 font-size がズームに対応するようにするには、ビューポート相対値を他の値の調整として適用する必要があります。これは、CSS で calc() 関数や、min()max()clamp() などの計算を受け入れる他の数学関数を使用して実現できます。calc(16px + 1vw)font-size は、ビューポートのサイズと、ピクセルの現在の(ズーム相対)サイズの両方に基づいています。vw 単位はズームの影響を受けませんが、基準値は影響を受けます。

その結果、ビューポートのサイズとユーザーのズーム設定の両方に対応する font-size が得られます。ユーザーが 200% にズームすると、ベース値は 2 倍の大きさ(32px)でレンダリングされますが、レスポンシブ値は変更されません。1000px ビューポートでは、最初は font-size16px + 10px = 26px になりますが、200% ズームでは、フォントサイズは 42px160% より少し大きい程度)までしか拡大されません。極端な問題ではないように思われるかもしれませんが、font-size がビューポートに基づくほど、ズームの有効性が低下します。

小さい画面では、font-size は主にベースのピクセル値から取得され、ズームに適切に対応します。しかし、大画面では、ビューポート サイズがレンダリングされたフォントサイズの大きな割合を占めるため、ズームの効果が薄くなります。これは、500% のズーム(ほとんどのブラウザでの最大値)では WCAG 1.4.4 で求められる 200% のフォントサイズの拡大が実現できなくなった時点で特に危険になります。しかし、それ以前の時点でも、ズームが有効でなくなるのはストレスになります。

フォントサイズとズームの有効性とビューポートの幅の関係を示すグラフ。フォントサイズは `calc(17px + 2.5vw)` として計算され、ビューポートの幅に応じて線形的に増加します。最大ズームを表す 500% ズームの線を見ると、ビューポートの幅が広くなるにつれてズームの効果が薄れ、ビューポートの幅が 2,040 ピクセルを超えるとフォント サイズを 200% 拡大できなくなっていることがわかります。
横軸は、0 から 2600px までのビューポートのサイズを表します。font-size の縦軸もピクセル単位で、calc(17px + 2.5vw) の結果を示しています。500% ズームラインは、同じビューポート幅の横軸を使用しますが、縦軸はパーセンテージとして扱います。

グラフの左端(0 ビューポートの幅)では、500% ズームが完全に有効になっています。ただし、ブラウザのサイズが大きくなると、その有効性は急速に低下し、(ズームできない)ビューポート単位が font-size の大きな要因になります。ブラウザの幅が 2040px の場合、最大 500% ズームではフォントサイズの 200% 倍の拡大しかできません。それ以降は、200% の有効なフォントズームはできなくなります。

この計算を最小値と最大値を含む clamp() 関数に移動することで、ズーム可能なテキストを保証する境界を適用できます。Maxwell Barvian 氏によると:

最大フォントサイズが最小フォントサイズの 2.5 倍以下の場合、少なくともすべての最新ブラウザで、テキストは常に WCAG SC 1.4.4 に合格します。

@media クエリと @container クエリは vw 単位と cqw 単位と同じ測定値に基づいているため、ブレークポイントを使用してフォントサイズを変更する場合にも同じロジックが適用されます。サイズの変化が大きすぎると、ズームは効果を発揮しません。次のビジュアリゼーションで、これらの値の相互作用を試すことができます。

font-size 値がユーザーのデフォルトに反応するようにする方法

ただし、calc(16px + 1vw) はユーザーのデフォルトのフォント設定にまだ対応していません。そのためには、px ではなく em または rem 単位を使用して、ベース(最小値と最大値)を設定します。すべてをまとめると、リンク先のデモと同じ結果が得られます。

html {
  font-size: clamp(1em, 17px + 0.24vw, 1.125em);
}

次のことに注意してください。

  • 最小値と最大値の両方で em 単位が使用されます。これはユーザー設定に基づいており、ズームに対応しています。
  • ズームに過度の影響を与えないように、追加の vw 値は最小限に抑えられています。
  • 最大サイズ(1.125em)は最小サイズ(1em)の 2.5 倍を大きく下回っているため、常に 200% の有効な font-size 値が可能です。

pow() を使用したタイポグラフィ スケール

ほとんどのデザインでは複数のフォントサイズが使用されています。タイポグラフィ スケールは、複数のフォントサイズの間の関係を表します。これは、基本サイズと、他のサイズを計算するための一連の乗数として表すことができます。CSS には、medium キーワード(ユーザーのフォントサイズ設定、またはデフォルトの 16px を参照)を基準とした組み込みのタイポグラフィ スケールが用意されています。完全なキーワード スケールは次のとおりです。

  • xx-small: 3/5(0.6)
  • x-small: 3/4(0.75)
  • small: 8/9(0.89)
  • medium: 1(他のサイズを乗算する基準サイズ)
  • large: 6/5(1.2)
  • x-large: 3/2(1.5)
  • xx-large: 2/1(2)
  • xxx-large: 3/1(3)

このスケールはルート font-size ではなくユーザーのデフォルトを基準としているため、サイトのルート font-size を変更すると、うまく機能しなくなります。ほとんどの作成者は、カスタム プロパティを使用して同様のタイプスケールを再作成します。同じ T シャツのサイズ名を使用する場合もあれば、数学的なスケールで上下する一連のステップを好む場合もあります。これらのスケールは、一般的な比率に基づいて生成するサードパーティ製ツールが多数あります。これらの比率は、主に西洋音楽のスケールから借用されています。

html {
  /* musical ratios */
  --minor-second: calc(16/15);
  --major-second: calc(9/8);
  --minor-third: calc(6/5);
  --major-third: calc(5/4);
  --perfect-fourth: calc(4/3);
  --augmented-fourth: sqrt(2);
  --perfect-fifth: calc(3/2);
  --major-sixth: calc(5/3);

  /* the golden ratio*/
  --golden-ratio: calc((1 + sqrt(5)) / 2);
}

ただし、CSS で独自のスケールを作成するために外部ツールは必要ありません。新しい pow() 関数を使用すると、1rem を独自のベースサイズとして、スケールを生成できます。

html {
  /* choose a ratio */
  --scale: 1.2;

  /* generate the scale using pow() */
  --xx-small: calc(1rem * pow(var(--scale), -0.5));
  --x-small: calc(1rem * pow(var(--scale), -0.25));
  --small: calc(1rem * pow(var(--scale), -0.125));
  --medium: 1rem;
  --large: calc(1rem * pow(var(--scale), 1));
  --x-large: calc(1rem * pow(var(--scale), 2));
  --xx-large: calc(1rem * pow(var(--scale), 3));
  --xxx-large: calc(1rem * pow(var(--scale), 4));

  /* change the ratio for different viewport sizes */
  @media (width > 50em) {
    --scale: var(--perfect-fourth);
  }
}

スケールの一貫性を保つために、全音階を使用する必要はありません。実際、一般的な 12pt タイポグラフィ スケールでは、1 ステップあたり約 5 つの分数を使用します。ここでは、大きいサイズはスケールで整数ステップを使用しますが、小さいサイズは分数を使用してスケールを遅いレートで調整します。

CSS ミックスインと関数を使用すると、そのロジックをさらに凝縮できます。また、progress() などの他の組み込みツールを使用すると、ある値から別の値にスムーズに調整されるスケールを簡単に作成できます。ただし、これらの機能はこのデモの範囲外です。

ページ内コンテナのサイズに対応する

vw または vi の代わりに cqi 単位を使用すると、これらの計算をすべてコンテナ クエリで機能させることができます。また、ユーザーの font-sizehtml 要素に残しておくと、すべての組版コンテナが 1rem としてそのユーザー設定を参照できるようになります。デモでは、グローバル タイプのルート html 要素ではなく body にタイプスケール全体が適用され、その後、type-set 属性を持つすべての要素のコンテナサイズに基づいてリセットされることがわかります。

これは常にコンテナ相対フォントサイズとのトレードオフになります。コンテキスト内の各要素のフォントサイズをより柔軟に調整できますが、ページ全体の整合性が損なわれます。どちらが重要かは、ユースケースの具体的な内容によって異なります。また、流動的なタイポグラフィ自体がトレードオフであり、ズームなどのユーザー コントロールの効果が低下することにも注意してください。

レスポンシブ タイポグラフィとタイポグラフィ スケールはデザイナーにとって優れたツールですが、必要がない場合は、複雑にする必要はありません。ユーザーのデフォルトと組み込みのタイプスケールも優れたオプションです。ただし、レスポンシブ(または流動的)なタイポグラフィを選択する場合は、さまざまなユーザーのデフォルト設定やズーム設定に対して結果がどのように動作するかを必ずテストしてください。お楽しみください!