---
title: "clamp() の余白指定で見落としがちなアクセシビリティ問題と解決策"
date: 2025-10-13
categories: column
author: 二俣
canonical: https://www.liberogic.jp/topics/20251014-clamp/
---

# clamp() の余白指定で見落としがちなアクセシビリティ問題と解決策

![](https://images.microcms-assets.io/assets/4b13731f29254025b91c8d846198ffc9/3827ef85dd434190ac334137507ce8c0/20251014-clamp.png)

余白の調整に clamp() で最小値～最大値で可変にする実装はレスポンシブ対応として非常に便利なのですが、アクセシビリティの拡大表示（ズーム）を考慮すると、ちょっとした落とし穴があるのです。WCAG対応を意識した実装を紹介します。

余白の調整に `clamp()` で最小値～最大値で可変にする実装が、最近ではよく使われますよね。

レスポンシブ対応として非常に便利なのですが、**アクセシビリティの拡大表示（ズーム）**を考慮すると、ちょっとした落とし穴があるのです。

## よくある clamp() の指定例

例えば、余白を `clamp()` で調整する場合は次のように書くことが多いでしょう。

```
`:root {
  --clamp-base: 16;
  --clamp-viewport-min: 375;
  --clamp-viewport-max: 1440;

  --spacing-lg-min: 24;
  --spacing-lg-max: 48;

  --spacing-lg-slope: calc(
    (var(--spacing-lg-max) - var(--spacing-lg-min)) / (var(--clamp-viewport-max) - var(--clamp-viewport-min))
  );
  --spacing-lg-intersection: calc(
    (var(--spacing-lg-max) - var(--clamp-viewport-max) * var(--spacing-lg-slope)) / var(--clamp-base)
  );
  --spacing-lg: clamp(
    calc(var(--spacing-lg-min) / var(--clamp-base) * 1rem),
    calc(var(--spacing-lg-intersection) * 1rem + 100 * var(--spacing-lg-slope) * 1vw),
    calc(var(--spacing-lg-max) / var(--clamp-base) * 1rem)
  );
}
`
```

詳細の説明は省きますが、

- スマートフォンでは `--spacing-lg-min` のサイズ
- PCでは `--spacing-lg-max` のサイズ
- その間は可変でスムーズに伸縮

となり、とても使い勝手の良いパターンですよね。

## アクセシビリティでの落とし穴って？

問題は、**WCAG 2.0 達成基準 1.4.4「テキストのサイズ変更」** に対応しようとする時です。

この基準はもともとスマートフォンが一般化する前に「PCで200%まで拡大しても閲覧できるように」という意図で策定されましたが、スマートフォンのブラウザにも同じ条件が適用されます。

実際にスマートフォンで 200%まで拡大すると、こんな現象が起こりがちです。

1. テキストの拡大（ズーム）が行われることで、`rem`単位を基準にした**余白まで一緒に拡大**してしまう。
2. これにより、本来のコンテンツを囲む**余白が過剰に広く**なってしまう。
3. 結果として、**コンテンツ表示エリアが極端に狭まり**、レイアウト崩れや見づらい状態になってしまう。

※ ただ現実問題として、WCAG準拠が義務とされている海外の政府系サイトなどをみてもあまり対応がされていない印象です。 おそらく費用対効果や、そもそもスマートフォンで200%に拡大というニーズ自体がほとんどないと思われることから、現場レベルでは「やらなくても大きな問題にはならない」と見なされているのかもしれません。

## この問題を解消するには？

テキスト拡大の影響を受ける `rem` ではなく、`vw` のようなビューポート基準の単位を使い、**ズームしても余白を必要以上に大きくしない**ことが重要です。

でも`vw`のみで指定すると `clamp()` の「最小値・最大値を制御できる」というメリットを活かせません。

そこで登場するのが `min()` 関数です！

`min()`は渡された値の中で「最も小さい値」を採用します。この特性を利用して、通常時と拡大時で適用される値を切り替えます。

書き方はこうです。

```
`--spacing-lg: min(
  calc(var(--spacing-lg-min) / var(--clamp-viewport-min) * 100vw),
  clamp(
    calc(var(--spacing-lg-min) / var(--clamp-base) * 1rem),
    calc(var(--spacing-lg-intersection) * 1rem + 100 * var(--spacing-lg-slope) * 1vw),
    calc(var(--spacing-lg-max) / var(--clamp-base) * 1rem)
  )
);
`
```

これを375 CSS pxで表示した時のminの最初の値は`--spacing-lg-min`の値である24pxをvwにした6.4vwになります。

`clamp()`の最小値は1.5rem = 24pxですが、200%拡大時には48pxになるため、左側の6.4vwの方が小さくなり、こちらが適用されることになります。

つまり、

- 通常時（100%表示）：
  - `clamp()`の値の方が`vw`基準の値よりも小さくなります。
  - `min()`は小さい方を採用するので、`clamp()`が効いて画面幅に応じて可変で表示されます。
- 拡大時（200%表示）:
  - `clamp()`内の`rem`が拡大によって大きくなり、`vw`基準の値の方が小さくなります。
  - `vw`基準の値が適用され、余白が画面幅に対する比率で固定されるため、過剰な拡大を防げます。

これで、「**レスポンシブな利便性**」と「**アクセシビリティへの配慮**」を両立できるわけです！

※ ちなみにPC表示では余白も含めて拡大された方がデザインのバランスが保たれることが多いため、`--clamp-viewport-min`を基準としてスマートフォンのみ適用としています。

## 実際の挙動を比較

上が clampのみ、下が min+clamp です。

スマホで200%に拡大をすると、違いがはっきり分かります。

※ iOS Safariはアドレスバー左のアイコンから、Android Chromeは右上のアイコンから拡大ができます。

## まとめ

- clamp() はレスポンシブな余白調整に便利
- ただし拡大表示すると余白まで拡大し、レイアウト崩れの可能性がある
- min() と組み合わせることで、**通常時は可変・拡大時は制御**というバランスの取れた対応が可能になる

WCAG対応を意識するなら、こうした実装を取り入れておくと安心ですね。 「スマホで200%の拡大まで気を配る」実装はまだ珍しいですが、普段の見やすさを損なわずに、アクセシビリティ面のリスクも抑えられます。

ちなみに、余白以外の細かい調整をしたい場合は、狭いブレイクポイントのメディアクエリを指定する方法もあります。

```
`@media (max-width: 239px) {
  /* 拡大時に適用したいCSS */
}
`
```

例えば 幅375pxの画面を200%に拡大した場合、ブラウザはビューポートの幅を「半分のサイズ（約188px）」として計算します。そのため、この狭い条件にマッチさせることができるんです。

※ 239px という値は一例で、将来の画面大型化の余地を残しつつ、通常表示には影響が出ないように調整して決めるとよいでしょう。

「clamp() + min()」と「狭いブレイクポイントのメディアクエリ」を組み合わせれば、より柔軟で安心なアクセシビリティ対応が可能になります！
