BLOGブログ

CSSのclamp()とvwで、文字サイズを画面幅に合わせる方法|小さすぎ・大きすぎを防ぐ計算式とSassの関数

竹節 大輝 /

Web制作・ホームページ制作

画面幅に合わせて文字を大きくしたくて font-size: 4vw; のように vw で指定したら、パソコンの広い画面で見出しが巨大になった。そんな経験はないでしょうか。 結論は、CSSの clamp() で「最小」と「最大」を決め、その間だけ vw で変えることです。 この記事では、Cruwのサイトの実際のCSSを例に、次の3つを紹介します。

  • clamp() の書き方と、どの画面幅で大きさが切り替わるかの読み方
  • 「画面幅375pxで24px、1440pxで34px」のように、2つの点から値を出す計算式
  • 計算をまかせる Sass の関数(Dart Sass の新しい書き方)

結論:font-size は clamp(最小, 画面幅で変わる値, 最大) で書く

.title {
  font-size: clamp(24px, 2.5vw, 34px);
}

clamp(最小, 推奨値, 最大) は、真ん中の値を使いつつ、最小より小さくならず、最大より大きくならないようにする関数です。 上の例では、画面幅に合わせて 2.5vw で大きさが変わりますが、24pxより小さくも、34pxより大きくもなりません。

  • vw だけ:画面幅に比例して、どこまでも小さく・大きくなる
  • clamp():画面幅に合わせて変わるが、決めた範囲から出ない

clamp() は、Chrome・Edge・Firefox・Safari の現在のバージョンで使えます(Safari は 13.1 から対応)。

vwだけで文字サイズを指定すると起きること

vw は「ブラウザの表示幅の1%」を表す単位です。画面幅375pxなら 1vw=3.75px、1440pxなら 1vw=14.4px になります(vw・vh の基本は「vw、vh、vmin、vmaxの使い方」で紹介しています)。

広い画面で大きくなりすぎる

スマートフォンのデザインに合わせて、見出しを 8vw(画面幅375pxで30px)にしたとします。同じ指定のまま画面幅1440pxで表示すると、115.2px になります。

画面幅375pxと1440pxで、8vwの見出しとclamp()の見出しを比べた画面。8vwは1440pxで115.2pxまで大きくなり、clamp()は34pxで止まっている
同じ指定を、画面幅375pxと1440pxで表示したところ(Chromeで表示して計測)

逆に、小さな画面では小さくなりすぎます。本文を画面幅375pxで14pxにしようと 3.733vw にすると、画面幅320pxでは約11.9pxになり、読みにくくなります。

ブラウザで拡大しても、文字が大きくならない

vw は画面の幅だけで決まるため、パソコンのブラウザで拡大(Ctrl+/⌘+)しても、vw だけで決めた文字はほとんど大きくなりません。文字を大きくして読みたい人には不便です。 後で紹介する計算式で、rem と vw を足す形にしているのは、このためです。

Cruwのサイトでは、スマートフォンのときだけvwにしていた

Cruwのサイトの古い部分では、Sass に次の関数を用意し、スマートフォン(画面幅767px以下)のときだけ vw にしています。デザインの基準幅は375pxです。

$baseWidth : 375;
@function vw($pixelsVw) {
  @return $pixelsVw / $baseWidth * 100vw;
}

.title {
  @media screen and (max-width:767px) {
    font-size: 30px;
    font-size: vw(30); // → 8vw
  }
}

font-size を2回書いているのは、vw が使えない古いブラウザでは30pxになるようにするためです。 vw になるのは画面幅767px以下だけなので、パソコンの画面で巨大になることはありません。ただ、767pxに近いタブレットでは 8vw=約61px になり、見出しとしては大きすぎます。メディアクエリで範囲を区切るより、clamp() で上限を決めるほうが確実です。

clamp()の書き方と、大きさが切り替わる画面幅の読み方

2026年9月に作り直したサービスページ(ホームページ制作・システム開発のページ)では、見出しを clamp() で指定しています。実際の値と、大きさが切り替わる画面幅は次のとおりです。

使っている場所と値最小のままの画面幅最大になる画面幅
大きな英字の見出し:clamp(44px, 5.6vw, 80px)約786pxまで約1429pxから
キャッチコピー:clamp(24px, 2.5vw, 34px)960pxまで1360pxから
お悩みへの答えの見出し:clamp(22px, 2.4vw, 32px)約917pxまで約1333pxから

真ん中が vw だけのときは、「最小 ÷ vwの数値 × 100」で、最小から変わり始める画面幅がわかります。

  • 24px ÷ 2.5 × 100 = 960px(ここまでは24px)
  • 34px ÷ 2.5 × 100 = 1360px(ここからは34px)

Chromeで画面幅を変えて計測すると、960pxで24px、1200pxで30px、1360px以上で34pxになりました。 この読み方を知っておくと、「スマートフォンでは最小のまま、パソコンの幅だけで変わる」のように、意図どおりの指定になっているかを確かめられます。

一方で、この書き方は「画面幅375pxのときに何px」といった、デザインカンプに合わせた指定がしにくい書き方です。そこで次の計算式を使います。

画面幅375px〜1440pxで、なめらかに変える計算式

「画面幅375pxで24px、1440pxで34px」のように、2つの点を決めて、その間をなめらかに変える方法です。 真ん中の値を「rem + vw」の形にします。

計算式

  1. 傾き =(最大の文字サイズ − 最小の文字サイズ)÷(最大の画面幅 − 最小の画面幅)
  2. vw の値 = 傾き × 100
  3. 固定の値(px) = 最小の文字サイズ − 傾き × 最小の画面幅
  4. 固定の値を16で割って rem にする(ブラウザの標準の文字サイズ16pxのとき)

例:375pxで24px、1440pxで34px

  1. 傾き =(34 − 24)÷(1440 − 375)= 10 ÷ 1065 ≒ 0.00939
  2. vw の値 = 0.00939 × 100 ≒ 0.939vw
  3. 固定の値 = 24 − 0.00939 × 375 ≒ 20.48px
  4. 20.48 ÷ 16 ≒ 1.28rem
.title {
  font-size: clamp(1.5rem, 1.28rem + 0.939vw, 2.125rem);
}

最小の24pxは1.5rem、最大の34pxは2.125remです。 確かめると、画面幅375pxで 20.48 + 3.52 = 24px、1440pxで 20.48 + 13.52 = 34px になります。Chromeで計測しても、768pxで約27.7px、1440pxで34pxと、計算どおりでした。

真ん中に rem を入れておくと、ブラウザで拡大したときに rem の分だけ文字が大きくなります。最小・最大も rem で書いておくと、ブラウザの文字サイズの設定も反映されます。

1つの値を px と vw で行き来したいときは、Cruwの「px→vw 変換・計算ツール」も使えます。CSSの中の px をまとめて vw に変える方法は「CSSのpxを一括vw置換」で紹介しています。

Sassで計算を関数にする(math.divを使う)

毎回手で計算するのは大変なので、Sass の関数にします。

古い書き方の「/」は、Dart Sassで警告が出る

先ほどの Cruwの vw() 関数は、割り算に / を使っています。Dart Sass(このテーマでは 1.55)でコンパイルすると、次の警告が出ます。

DEPRECATION WARNING: Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0.

Recommendation: math.div($pixelsVw, $baseWidth) or calc($pixelsVw / $baseWidth)

Dart Sass 2.0 では / での割り算が使えなくなる予定です。新しく書くときは math.div() を使います。

@use "sass:math";

$base-width: 375;

@function vw($px) {
  @return math.div($px, $base-width) * 100vw;
}

2つの点から clamp() を作る関数

@use "sass:math";

// px を rem に(小数第3位まで)
@function to-rem($px) {
  @return math.div(math.round(math.div($px, 16) * 1000), 1000) * 1rem;
}

// 画面幅 $min-w〜$max-w の間で、$min-px〜$max-px に変える
@function fluid($min-px, $max-px, $min-w: 375, $max-w: 1440) {
  $slope: math.div($max-px - $min-px, $max-w - $min-w);
  $base: $min-px - $slope * $min-w;
  $vw: math.div(math.round($slope * 100 * 1000), 1000) * 1vw;
  @return clamp(#{to-rem($min-px)}, #{to-rem($base)} + #{$vw}, #{to-rem($max-px)});
}

.title {
  font-size: fluid(24, 34);
}
.text {
  font-size: fluid(16, 18);
}

コンパイルすると、次の CSS になります。

.title {
  font-size: clamp(1.5rem, 1.28rem + 0.939vw, 2.125rem);
}

.text {
  font-size: clamp(1rem, 0.956rem + 0.188vw, 1.125rem);
}

#{} で文字として組み立てているのは、Sass に clamp() の中を計算させず、そのまま CSS に出すためです。 デザインカンプの「スマートフォンで何px、パソコンで何px」をそのまま書けるので、見出しの大きさをそろえやすくなります。

よくある質問

本文の文字にも clamp() を使ったほうがいいですか?

本文は、16px(1rem)前後の固定でも十分なことが多いです。使う場合も、16pxから18pxくらいの小さな幅にとどめると、読みやすさを保てます。画面幅で大きく変えて効果が出るのは、見出しやキャッチコピーです。

最小・最大は px と rem のどちらで書けばいいですか?

ブラウザの文字サイズの設定を反映したいなら rem がおすすめです。px で書いても、ブラウザの拡大には合わせて大きくなります。

行間(line-height)も vw で指定したほうがいいですか?

line-height: 1.6; のように単位なしで指定すれば、文字の大きさに合わせて自動で変わります。vw で指定する必要はありません。

まとめ

  • 文字サイズを vw だけで決めると、広い画面で大きくなりすぎ、狭い画面で小さくなりすぎる
  • clamp(最小, 画面幅で変わる値, 最大) で範囲を決める。真ん中が vw だけなら「最小 ÷ vwの数値 × 100」で、変わり始める画面幅がわかる
  • 「375pxで24px、1440pxで34px」のように2点で決めるなら、rem + vw の計算式か、Sass の関数にまかせる

Cruwでは、長野県上田市を拠点に、スマートフォンからパソコンまで見やすいホームページの制作を行っています。「スマートフォンで見出しが崩れる」「今のサイトの CSS を整理したい」といったご相談も、ホームページ制作のページからお気軽にどうぞ。

GoogleのAI検索で「Cruwのブログ」を優先表示しませんか?

Googleの最新機能では、お気に入りのサイトを「優先するソース」として登録できるようになりました。登録していただくと、GoogleのAIモードやAI Overviewsが回答をつくる際、当サイトの情報を優先的に参照・表示してくれるようになります。

これからも地域ビジネスに役立つ最新のWebマーケティング情報を発信していきますので、ぜひ優先ソースへのご登録をお願いいたします!