CSS clamp() 実践ガイド ―
メディアクエリを減らして、滑らかなレスポンシブを実現する

文字サイズ、余白、幅——レスポンシブ対応のたびにメディアクエリを何本も書いていませんか? clamp() を使えば、1行で「最小値・推奨値・最大値」を定義し、ビューポートに応じた滑らかな変化を実現できます。

メディアクエリの「カクカク問題」を感じていませんか

レスポンシブデザインを組むとき、見出しの文字サイズをブレイクポイントごとに切り替える——これ、現場では日常的にやりますよね。たとえばスマホで18px、タブレットで26px、デスクトップで36pxのように。

でも、ブラウザの幅を少しずつ動かしてみてください。599pxから600pxに変わった瞬間、文字サイズがパッと切り替わる。これが「カクカク問題」です。ブレイクポイントの境界でサイズが不連続にジャンプするので、ユーザーの画面サイズによっては文字が大きすぎたり小さすぎたりする中途半端な状態が生まれます。

clamp() は、この問題をたった1行で解決するCSSの関数です。「最小値」「推奨値(ビューポートに連動する計算式)」「最大値」の3つを指定するだけで、画面幅に応じて値が滑らかに変化します。メディアクエリを一本も書かずに。

📌 ポイント
clamp() は Chrome 79+、Firefox 75+、Safari 13.1+、Edge 79+ で対応しており、2026年現在ほぼすべてのモダンブラウザで使えます。IE対応が不要なプロジェクトなら、安心して導入できます。

clamp() の基本——3つの値を理解する

clamp() の構文はシンプルです。引数を3つ取ります。

clamp() の基本構文
font-size: clamp(18px, 2vw + 12px, 36px);

/*        ┌─────────┐  ┌───────────┐  ┌─────────┐ */
/*        │ 最小値   │  │ 推奨値     │  │ 最大値   │ */
/*        │ MIN      │  │ PREFERRED  │  │ MAX      │ */
/*        └─────────┘  └───────────┘  └─────────┘ */

それぞれの役割を整理しましょう。第1引数(MIN)は下限です。どんなに画面が小さくても、値はこれより小さくなりません。第2引数(PREFERRED)は「理想値」で、ビューポート幅に連動する計算式を入れます。ここが clamp() の核心です。第3引数(MAX)は上限。画面がどれだけ大きくても、値はこれを超えません。

動作を身近な例えで言うと、サーモスタット(温度調節器)に似ています。「下限18度・上限28度」と設定しておけば、外気温に応じて室温はその範囲内で自動調整される。clamp() も同じで、ビューポート幅という「外気温」に応じて、最小と最大の間で値が滑らかに動くのです。

推奨値の計算式の考え方

推奨値には vw(ビューポート幅の1%)を使った計算式を入れるのが一般的です。2vw + 12px のように「vw単位 + 固定値」の形にすると、画面幅が広がるにつれて値が緩やかに増加し、固定値の部分がベースラインとして機能します。

推奨値の構造
/* vw の係数が大きいほど、画面幅による変化が急になる */
font-size: clamp(16px, 1vw + 12px, 24px);  /* 緩やかな変化 */
font-size: clamp(16px, 4vw + 2px, 40px);  /* 急な変化 */

では、実際に動くデモで確認してみましょう。ブラウザの幅を変えると、見出しと本文のサイズが滑らかに変化するのがわかります。

▶ Live Demo — clamp() によるフルイドタイポグラフィ

見出しのサイズが画面幅で変わります

この本文も clamp() でサイズ指定しています。ブラウザの幅を広げたり縮めたりしてみてください。メディアクエリなしで、文字サイズが滑らかに変化するのが確認できます。

比較のために、メディアクエリで同じ範囲をカバーした場合のデモも置いておきます。ブラウザ幅を少しずつ変えると、ブレイクポイントの境界で文字サイズがカクッと切り替わるのがわかるはずです。

▶ Live Demo — メディアクエリによるステップ式変化(比較用)

メディアクエリで切り替えた見出し

💡 現場の経験則
推奨値の計算を手動でやるのが面倒なら、Utopiaclamp() Calculator といったオンラインツールを使うと、最小ビューポート幅・最大ビューポート幅・最小フォントサイズ・最大フォントサイズを入力するだけで最適な clamp() 式を自動生成してくれます。

現場で使える実践パターン

clamp() は font-size だけのものではありません。<length> を受け取るほぼすべてのCSSプロパティで使えます。ここからは、実務でよく登場するパターンを3つ紹介します。

パターン1:余白(padding / margin)のフルイド化

セクションの上下パディングを、スマホでは小さめ、デスクトップでは大きめにしたい——これもメディアクエリなしで実現できます。

✅ clamp() で滑らかな余白
.hero {
  padding: clamp(12px, 3vw, 48px);
}
▶ Live Demo — パディングのフルイド化
ブラウザ幅を変えてみてください。この要素の padding が滑らかに変化します。
❌ やりがちなNG:メディアクエリの連打
.hero {
  padding: 12px;
}
@media (min-width: 600px) {
  .hero { padding: 24px; }
}
@media (min-width: 1024px) {
  .hero { padding: 48px; }
}
/* 3つのブレイクポイントで段階的に変わる。境界でジャンプする。 */

パターン2:コンテナ幅の制御

カードやモーダルなど、「最小幅と最大幅の間でビューポートに応じた幅にしたい」というケースです。max-widthwidth: 100% の組み合わせで実現することも多いですが、clamp() ならより直感的に書けます。

コンテナ幅を clamp() で制御
.card {
  width: clamp(200px, 50vw, 600px);
  /* 最小200px、最大600px。間は画面幅の50%で追従 */
}
▶ Live Demo — カード幅のフルイド制御

width: clamp(200px, 50vw, 600px)

ブラウザ幅に応じてこのカードの幅が変わります

パターン3:Grid / Flexbox の gap をフルイドに

グリッドレイアウトの gap も clamp() との相性が良いプロパティです。スマホでは詰めたいけど、デスクトップでは余裕を持たせたい——そんなケースにぴったりです。

gap を clamp() で指定
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(8px, 2vw, 24px);
}
▶ Live Demo — グリッドの gap がフルイドに変化
1
2
3
4
5
6

応用:フルイドな見出し階層を一括設計する

実際のプロジェクトでは、h1・h2・h3それぞれに clamp() を設定して、一貫したタイプスケール(文字サイズの階層構造)を作ることになります。ここで大事なのは、各レベルの「変化率」を揃えること。見出しだけが急激に大きくなって本文との差がちぐはぐにならないよう、vw の係数を意識して設計します。

フルイド・タイプスケールの設計例
:root {
  --font-h2:   clamp(22px, 1.5vw + 14px, 34px);
  --font-h3:   clamp(17px, 1vw + 11px, 24px);
  --font-body: clamp(14px, 0.5vw + 11px, 18px);
}

h2 { font-size: var(--font-h2); }
h3 { font-size: var(--font-h3); }
p  { font-size: var(--font-body); }

ポイントは、vw の係数が上位の見出しほど大きく、本文に近づくほど小さくなっている点です。こうすることで、スマホでは見出しと本文のサイズ差が控えめに、デスクトップでは見出しがしっかり目立つ——という理想的な階層が自動的に作られます。

▶ Live Demo — フルイド・タイプスケール

h2 — セクション見出し

h3 — サブ見出し

本文テキストです。ブラウザ幅を変えると、見出しと本文の比率が自然に変化するのが確認できます。デスクトップでは見出しが大きく目立ち、スマホでは差が控えめになります。

CSS Custom Properties(カスタムプロパティ)と組み合わせれば、デザイントークンとしてプロジェクト全体で再利用しやすくなります。変更も :root の1箇所を直すだけで済むので、メンテナンス性も高い。

アクセシビリティの注意点——ズームとWCAG SC 1.4.4

clamp() は便利ですが、アクセシビリティの観点で知っておくべき注意点があります。WCAGの達成基準 1.4.4(テキストのサイズ変更)は、「テキストが元のサイズの200%まで拡大できること」を求めています。

問題は、ブラウザのズーム機能と vw 単位の関係にあります。ユーザーがブラウザを500%にズームしても、ビューポート自体のサイズは変わりません。つまり、vw ベースの値はズームしてもスケールしないのです。rempx はズーム時にきちんと拡大されますが、vw 成分が大きいと、ズームしてもテキストが十分に大きくならないケースが出てきます。

⚠️ 注意
WCAG SC 1.4.4 を安全にクリアするための目安:clamp() の最大値を、最小値の2.5倍以内に収めることが推奨されています。たとえば最小値が16pxなら、最大値は40px以下にする。これを超える場合は、実際にブラウザの500%ズームでテストして、テキストが元の200%以上に拡大されることを確認してください。

rem 単位を使うとさらに安全

px 指定だとユーザーのブラウザフォント設定が反映されませんが、rem を使えばユーザーの設定に連動します。clamp() の最小値・最大値を rem で指定するのがベストプラクティスです。

✅ rem を使ったアクセシブルな clamp()
h1 {
  font-size: clamp(1.125rem, 1.5vw + 0.75rem, 2.25rem);
  /* 18px〜36px相当。最大値は最小値の2倍 → WCAG安全圏 */
}
❌ 比率が大きすぎるNG例
h1 {
  font-size: clamp(1rem, 5vw + 0.5rem, 4rem);
  /* 16px〜64px相当。最大値は最小値の4倍 → WCAGに抵触する可能性 */
}

まとめ

  • clamp(MIN, PREFERRED, MAX) は「最小値・推奨値・最大値」の3つを指定し、ビューポートに応じた滑らかな値変化を1行で実現するCSS関数。
  • 推奨値にはvw単位を含む計算式(例:2vw + 12px)を入れるのが一般的。vwの係数が大きいほど変化が急になる。
  • font-size だけでなく、padding、margin、width、gap など length を受け取るほぼすべてのプロパティで利用可能。
  • メディアクエリのようなステップ式の切り替えではなく、連続的な変化になるため、どの画面幅でも自然な見た目が保たれる。
  • CSS Custom Properties と組み合わせてフルイド・タイプスケールを設計すると、プロジェクト全体で一貫したレスポンシブタイポグラフィが実現できる。
  • WCAG SC 1.4.4 に準拠するため、clamp() の最大値は最小値の2.5倍以内に抑え、最小値・最大値はrem単位で指定するのがベストプラクティス。
  • 推奨値の計算が面倒な場合は、Utopia や clamp() Calculator などのオンラインツールで自動生成できる。