下記がとても実践的で参考になったので、情報を補足しながら紹介します。
はじめに
Webデザインにおいて、文字サイズの一貫性とレスポンシブ性は重要な要素です。特に異なるデバイスやビューポートサイズに対して、スムーズに適応する文字サイズの実装は、多くの開発者が直面する課題となっています。
従来、このような適応型のタイポグラフィを実現するには、JavaScriptを使用したり、複雑なCSSの計算を行ったりする必要がありました。しかし、モダンなCSSの機能であるcalc()
、clamp()
、CSS変数を組み合わせることで、よりシンプルかつ効果的な解決策を実現できます。
前提知識
この記事を理解するために必要な知識:
- CSSの基本的な理解
- CSS変数(カスタムプロパティ)の基本
- レスポンシブデザインの概念
- モダンブラウザでのCSS機能サポート
実装の基本概念
calc()関数の仕組み
calc()
関数は数値計算を行うCSS関数ですが、いくつかの重要な制限があります:
-
単位なしの数値とピクセル値の暗黙的な変換ができない
-
calc(5px + 5)
は無効な式 -
calc(5px + 5px)
のように単位をそろえる必要がある
-
-
ピクセル値同士の除算ができない
-
calc(10px / 2px)
は無効 -
calc(10px / 2)
のように除数は単位なしの数値にする
-
-
ピクセル値同士の乗算ができない
-
calc(5px * 2px)
は無効 -
calc(5px * 2)
のように片方は単位なしの数値にする
-
これらの制限を回避するため、以下の巧みな戦略が紹介されています:
:root {
/* 単位なしの数値として定義 */
--min-size: 12; /* 最小フォントサイズ */
--max-size: 18; /* 最大フォントサイズ */
--container-min: 320; /* 最小コンテナ幅 */
--container-max: 2400; /* 最大コンテナ幅 */
}
.container-adaptive {
/* サイズの計算 */
--font-size: calc(
/* 基本サイズ(単位なしの数値にピクセル単位を適用) */
var(--min-size) * 1px +
/* 最大サイズと最小サイズの差分 */
(var(--max-size) - var(--min-size)) *
/* コンテナサイズの現在位置を計算 */
(100cqw - var(--container-min) * 1px) /
/* コンテナサイズの範囲で正規化 */
(var(--container-max) - var(--container-min))
);
}
clamp()関数による範囲の制御
clamp()
関数は値を指定された範囲内に収める機能を提供します:
.container-adaptive {
/* clamp(最小値, 推奨値, 最大値) */
font-size: clamp(
var(--min-size) * 1px, /* これより小さくならない */
var(--font-size), /* 可能ならこの値を使用 */
var(--max-size) * 1px /* これより大きくならない */
);
}
この組み合わせにより、以下の利点が得られます:
-
適切な範囲での制御
- 最小値以下にならない
- 最大値以上にならない
- その間は計算された値を使用
-
スムーズな変化
- ビューポートサイズの変化に応じて連続的に変化
- 急激な変化を避けられる
実装パターン
ビューポートベースの実装
ブラウザウィンドウ全体を基準にする場合:
.viewport-adaptive {
/* ビューポート幅に基づく計算 */
--font-size: calc(
var(--min-size) * 1px +
(var(--max-size) - var(--min-size)) *
/* 100vwはビューポート幅全体を表す */
(100vw - var(--viewport-min) * 1px) /
(var(--viewport-max) - var(--viewport-min))
);
font-size: clamp(
var(--min-size) * 1px,
var(--font-size),
var(--max-size) * 1px
);
}
コンテナベースの実装
特定のコンテナ要素を基準にする場合:
/* コンテナの定義 */
.container {
/* コンテナクエリの有効化 */
container-type: inline-size;
container-name: main;
}
.container-adaptive {
--font-size: calc(
var(--min-size) * 1px +
(var(--max-size) - var(--min-size)) *
/* 100cqwは現在のコンテナ幅を表す */
(100cqw - var(--container-min) * 1px) /
(var(--container-max) - var(--container-min))
);
font-size: clamp(
var(--min-size) * 1px,
var(--font-size),
var(--max-size) * 1px
);
}
/* コンテナクエリの使用例 */
@container main (min-width: 400px) {
.container-adaptive {
/* コンテナが400px以上の時のスタイル */
}
}
実装の際は、以下の点に考慮が必要かもしれません:
- デザインシステムの粒度
- コンポーネントの再利用性
- ブラウザサポートの要件(コンテナクエリは比較的新しい機能)
スケーラブルなユーティリティクラスの作成
再利用可能なタイプスケールを構築するために、ユーティリティクラスを設定します:
/* ベースとなる変数の定義 */
:root {
--scale: 1.25; /* スケール比率 */
--base-size: 1rem; /* 基準サイズ */
/* ビューポート/コンテナの制約 */
--min-viewport: 320;
--max-viewport: 2400;
}
/* スケールレベルの定義 */
.text-md, .text-lg, .text-xl {
container-type: inline-size;
}
/* 中サイズテキスト */
.text-md {
--min-size: 14;
--max-size: 16;
font-size: clamp(
var(--min-size) * 1px,
calc(var(--min-size) * 1px + (var(--max-size) - var(--min-size)) *
(100cqw - var(--min-viewport) * 1px) /
(var(--max-viewport) - var(--min-viewport))),
var(--max-size) * 1px
);
}
/* 大サイズテキスト */
.text-lg {
--min-size: 16;
--max-size: 20;
font-size: clamp(
var(--min-size) * 1px,
calc(var(--min-size) * 1px + (var(--max-size) - var(--min-size)) *
(100cqw - var(--min-viewport) * 1px) /
(var(--max-viewport) - var(--min-viewport))),
var(--max-size) * 1px
);
}
/* 特大サイズテキスト */
.text-xl {
--min-size: 20;
--max-size: 24;
font-size: clamp(
var(--min-size) * 1px,
calc(var(--min-size) * 1px + (var(--max-size) - var(--min-size)) *
(100cqw - var(--min-viewport) * 1px) /
(var(--max-viewport) - var(--min-viewport))),
var(--max-size) * 1px
);
}
使用例:
<div class="container">
<h1 class="text-xl">大見出し</h1>
<h2 class="text-lg">中見出し</h2>
<p class="text-md">本文テキスト</p>
</div>
現在の制限事項
-
ブラウザサポート
- コンテナクエリ(cqw)は比較的新しい機能
- フォールバックの実装を検討する必要がある
-
パフォーマンスへの影響
- 複雑な計算を含むため、大量の要素に適用する場合は注意が必要
注:参考記事ではcalc()関数でのrem単位の使用に制限があるとされていますが、現在の主要なモダンブラウザではこの制限は解除されており、rem単位を自由に使用できます。
トラブルシューティング
デバグが大変だという感想を持ちました。
ありそうな問題と解決方法
-
計算結果が期待通りでない
- 単位の使用方法を確認(単位なしの数値とピクセル値の混在に注意)
- clamp()の最小値と最大値が適切か確認
-
スムーズな変化が見られない
- コンテナ/ビューポートの最小値と最大値の範囲が適切か確認
- 中間値の計算が正しく行われているか確認
-
古いブラウザでの対応
/* フォールバックの実装例 */
.adaptive-text {
/* 基本サイズをフォールバックとして設定 */
font-size: 16px;
/* モダンブラウザ向けの実装 */
font-size: clamp(var(--min-size) * 1px, var(--font-size), var(--max-size) * 1px);
}
まとめ
フルードタイプスケールは、モダンなCSSの機能を活用することで、より柔軟でレスポンシブなタイポグラフィを実現します。本記事で紹介した実装方法には以下の利点があります:
- メンテナンス性の高いCSS変数の活用
- ブレイクポイントに依存しない連続的な変化
- コンポーザブルなユーティリティクラスによる柔軟な設定
これらの技術を適切に組み合わせることで、より洗練されたWebタイポグラフィを実現できます。