clamp()を使ってフォントサイズはレスポンシブで自動調整せよ【ジェネレーターとSass関数の使いかたも】|しょーごログ (shogo-log.com)
レスポンシブでフォントサイズや要素のサイズを変える時に、毎回メディアクエリで、画面幅毎にこんな指定をしていませんか?
@media screen and (max-width:768px) {
.title {
font-size: 14px;
}
@media screen and (min-width:768px) and (max-width:1024px) {
.title {
font-size: 24px;
}
@media screen and (min-width:1024px) {
.title {
font-size: 32px;
}
Copy
実は、今回紹介するclamp()を使用すれば、こんな煩わしい指定を毎回しなくても、一行で実装できます!
.title {
font-size: clamp(0.875rem, -2.5rem + 7.03vw, 2rem);
}
Copy
この記事ではclamp()を実際に利用する際に必須となるジェネレーターの使い方や、scss関数の組み方も解説するので、
是非この記事を通してclamp()を今日から利用していってもらえればと思います。
Sassを使わない人はジェネレーターを使って、Sassを使う人は関数でラクラクclamp()でレスポンシブを管理できるようになります。
目次
- clamp()の対応ブラウザ
- clamp()とは
- clamp()の推奨値ってどうやって計算するの?
- clamp()の利用方法❶ジェネレーターを使う
- clamp()の利用方法❷sassの関数を使う
- clamp()の実用例
- clamp()がsafariで動かない場合
- clamp()のデメリット
- まとめ clamp()の可能性は無限大!
スポンサーリンク
clamp()とは
clamp()はCSSの関数で、最小値、推奨値、最大値の3つの引数を取ります。
clamp(最小値, 推奨値, 最大値)
Copy
最小値 | 要素が取ることができる最小の値を示します。通常、画面が非常に小さい場合や、コンテンツが非常に狭い場合にこの値が適用されます。 |
推奨値 | 常の状況で要素が持つべき推奨される値です。通常、この値が画面サイズやコンテンツの幅に応じて柔軟に変化します |
最大値 | 要素が取ることができる最大の値を示します。通常、画面が非常に大きい場合や、コンテンツが非常に広い場合にこの値が適用されます。 |
この説明で理解できる人はほぼいないでしょう。
例えば、
.container {
width: clamp(300px, 50vw,1000px);
}
Copy
という記述だと、基本的にwidthが50vwで動きつつ、300pxより小さくならなくならず、1000pxより大きくならなくなるので、
要素がスマホ時に小さすぎたり、PC幅以上の大画面時に大きすぎる状態を防ぐことができます。
具体的な動作を見てみましょう。
これまでのレスポンシブ対応では、テキストサイズは以下のように、メディアクエリを使用してPC、タブレット、SPで段階的に切り替えている人が多かったかもしれません。
もしかしたら、vwでレスポンシブ対応している人もいるかもしれませんが、その場合に大画面時に要素が巨大化して違和感が発生しているケースがあります。
要は、「PC幅〜のときはPCの固定サイズ、タブレット付近はよしなにフレキシブルに変化して、SPのときはSPデザインの固定サイズ」にしたいのですよね。
それ、clamp()を使えば簡単にできます。例えば以下は滑らかにフォントサイズが変わっているのが分かると思います。
ここではファーストビューのメインコピーだけclamp()を適用しています。
ここで使用したコードは以下ですが、
font-size: clamp(3rem, 1rem + 6.67vw, 6rem);
Copy
これをメディアクエリを使って書くと、結構めんどくさいです。
@media screen and (max-width: 768px) {
/* 768px以下の場合 */
font-size: 3rem;
}
@media screen and (min-width: 768px) and (max-width: 1440px) {
/* 768px以上1440px以下の場合 */
font-size: calc(1rem + 6.67vw);
}
@media screen and (min-width: 1440px) {
/* 1440px以上の場合 */
font-size: 6rem;
}
Copy
推奨値の補足
1rem + 6.67vwという数値は、768px~1440pxの範囲でいい感じにレスポンシブすることを示していますが、この数式は自動で出せるので詳しくは後述します。
もう一つ例を見てみましょう。
こちらはコンテナのwidthと中の見出しのfont-sizeに対してclamp()を使用した例です。
まずコンテナのwidthはこうなっています。
width: clamp(320px, 0.682rem + 82.42vw, 1000px);
Copy
これをメディアクエリを使うと、
@media screen and (max-width: 768px) {
/* 768px以下の場合 */
width: 320px;
}
@media screen and (min-width: 768px) and (max-width: 1440px) {
/* 768px以上1440px以下の場合 */
width: calc(0.682rem + 82.42vw);
}
@media screen and (min-width: 1440px) {
/* 1440px以上の場合 */
width: 1000px;
}
Copy
font-sizeに関しては以下になっています。
font-size: clamp(1.5rem, 0.364rem + 4.85vw, 4rem);
Copy
これをメディアクエリを使うと、
@media screen and (max-width: 768px) {
/* 768px以下の場合 */
font-size: 1.5rem;
}
@media screen and (min-width: 768px) and (max-width: 1440px) {
/* 768px以上1440px以下の場合 */
font-size: calc(0.364rem + 4.85vw);
}
@media screen and (min-width: 1440px) {
/* 1440px以上の場合 */
font-size: 4rem;
}
Copy
ただここで疑問が出てきます。
clamp(1.5rem, 0.364rem + 4.85vw, 4rem)
Copy
真ん中の推奨値である、0.364rem + 4.85vwはどうやって出せばいいのでしょうか?
clamp()の推奨値ってどうやって計算するの?
デザイナーさん
でも、タブレット付近をよしなにしてくれる真ん中のremとvwが+されてるところとか、どうやって計算すればいいの?
なんかめんどくさそう。。。
これには2つの方法があります。
clamp()を利用する方法
- ジェネレーターを使う(初心者におすすめ)
- scss関数を組む(Sassに自信ニキにおすすめ)
順番に解説します。
clamp()の利用方法❶ジェネレーターを使う
お試しでとりあえずclamp()を使う程度なら、脳死で「Min-Max-Value Interpolation」を利用して、推奨値を算出すればいいかと思います。
例えばフォントサイズで、
PCデザイン1200pxのときは64px
SPデザイン375pxのときは24px
その間375px~1200pxはよしなに動いて欲しい
こんなときは、この画像のように入力すればOKです。
単位がremになっていますが、どうしてもpxを使いたい人は、remの数値を16倍してpxにしてもいいと思います。
補足:remとpxについて
今回の本題とずれますが、
まさひろくん
remじゃないとダメなのかな?
と思われる方がいるかもなので、補足です。
基本的にアクセシビリティなどの観点からremを使ったほうが良い場合が多く、sassの関数で簡単にpx→remに変換できるので、
まだremに慣れていない人はこのタイミングで導入するといいかなと思います。
// 基準となるフォントサイズを設定
$baseFontSize: 16px;
// pxをremに変換する関数
@function rem($pxValue) {
@return ($pxValue / $baseFontSize) * 1rem;
}
// 使用例
.box h1 {
font-size: rem(24px); // 24pxを16px基準のremに変換
}
Copy
もしclamp()を使うまでも無い場面では、この関数を使えばいいと思います。
clamp()の利用方法❷sassの関数を使う
ありさちゃん
毎回ジェネレーター使うの煩わしいですね。。。
こう思ったなら、Sassで関数を組めばよいでしょう。
以下がclamp()を生成する関数です。
@function rclamp($min, $max, $minViewport, $maxViewport) {
$vwScale: ($max - $min) / ($maxViewport - $minViewport); // vw単位でのスケールを計算
$baseOffset: $min - $minViewport * $vwScale; // 基準となる最小値からのオフセットを計算
$minRem: $min / 16; // 最小値をremに変換
$maxRem: $max / 16; // 最大値をremに変換
$baseOffsetRem: $baseOffset / 16; // オフセットをremに変換
$vwScaleRem: $vwScale * 100; // vwスケールを調整
@return clamp(#{$minRem}rem, #{$baseOffsetRem}rem + #{$vwScaleRem}vw, #{$maxRem}rem);
}
// 使用例
.example {
font-size: rclamp(24, 64, 375, 1200);
}
Copy
実際に使う際には、
rclamp(最小値, 最大値, 最小viewport,最大viewport)
Copy
を入力することで、コンパイル後のCSSでclamp()が生成されます。
関数定義の下に使用例を載せていますが、この使用例だと、以下の画像と同じ値が出力されます。
補足:自作関数の詳細説明
この関数の詳細な動きを知りたい人向けに、一応噛み砕いて説明しておきます。
とはいえかなり難しいので、理解できなければとりあえず飛ばして関数だけ利用しておけばOKです。
関数定義
@function rclamp($min, $max, $minViewport, $maxViewport) {
Copy
rclamp
関数は、4つのパラメータを受け取ります。$min
と$max
は、フォントサイズの最小値と最大値(ピクセル単位で指定)。$minViewport
と$maxViewport
は、このフォントサイズ調整を適用するビューポートの最小幅と最大幅(ピクセル単位)。
計算
$vwScale: ($max - $min) / ($maxViewport - $minViewport); // vw単位でのスケールを計算
$baseOffset: $min - $minViewport * $vwScale; // 基準となる最小値からのオフセットを計算
Copy
$vwScale
は、ビューポートが$minViewport
から$maxViewport
に変化する間に、フォントサイズがどれだけ変わるかの比率を計算します。$baseOffset
は、最小ビューポート幅でフォントサイズが$min
になるように調整するためのオフセットを計算します。
単位変換
$minRem: $min / 16; // 最小値をremに変換
$maxRem: $max / 16; // 最大値をremに変換
$baseOffsetRem: $baseOffset / 16; // オフセットをremに変換
$vwScaleRem: $vwScale * 100; // vwスケールを調整
Copy
- ここで、フォントサイズとオフセットの単位をピクセルから
rem
に変換しています。通常、1remはブラウザの基本フォントサイズ(多くの場合16px)に相当します。これにより、スタイルの設定がより柔軟になります。 $vwScaleRem
は、vw
スケールを100倍にして、vw単位がビューポート幅の百分率を反映するように調整しています。
clamp() 関数のリターン部分
@return clamp(#{$minRem}rem, #{$baseOffsetRem}rem + #{$vwScaleRem}vw, #{$maxRem}rem);
Copy
- ここでは計算された値を使用してCSSの
clamp()
を構築し、フォントサイズがビューポートの幅に応じて柔軟に調整されるようにします。 clamp()
の第一引数は最小値、第三引数は最大値、第二引数はビューポート幅に応じて変化する中間の値です。
使用例(ここが理解できればOK)
ここまで関数を指定したので、その使用例です。
この関数の使い方だけ覚えて貰えれば今回は特に問題ありません。
.example {
font-size: rclamp(24, 64, 375, 1200);
}
Copy
ここで指定された数値は、ピクセル単位での最小値、最大値、ビューポートの最小幅、最大幅です。
この値の場合、CSSにコンパイルしてみると、実際にSassで定義した独自関数の中では以下の処理が行われます。
$minRem = 24 / 16 = 1.5rem
$maxRem = 64 / 16 = 4rem
$vwScale = (64 - 24) / (1200 - 375) = 40 / 825 ≈ 0.0484848
$vwScaleRem = 0.0484848 * 100 = 4.84848vw
$baseOffset = 24 - 375 * 0.0484848 ≈ 6.18181818
$baseOffsetRem = 6.18181818 / 16 ≈ 0.38636364rem
Copy
そうしてこの関数内での計算の結果、CSSのclamp()として出力された時に、
clamp(1.5rem, 0.38636364rem + 4.8484848485vw, 4rem)
Copy
というように最小、最大値はremで、推奨値では、rem+vwの値が出力されます。
これによって、タブレット付近でいい感じに大きさが変化してくれるわけです。
しょーご
Sassの関数の処理がわからなかった人は、この具体的数値を入れた処理の流れと同時に見ると分かりやすいと思います。
clamp()の実用例
では、今日学んだことの実践です。
例えばPCデザイン時に1440pxでfont-size96pxだったとして、
スマホデザインでは、375pxでfont-size48pxのときはどう設定しますか?
ジェネレーターとSass独自関数の2つの例をみていくと、
ジェネレーターを使う場合は、以下のような指定になり、
Sassの関数を使う場合は、
font-size: rclamp(48, 96, 375, 1440);
Copy
この指定にすればいいですね!
試しにCSSに出力された結果を見ると、
font-size: clamp(3rem, 1.9436619718rem + 4.5070422535vw, 6rem);
Copy
となっていて、ジェネレーター出力の数値よりも桁数が多いですが、ほぼ同じ数値になっているのが分かります。
clamp()がsafariで動かない場合
safariのバージョンによってはclamp関数が動かない場合があるので、そのときは
* {
min-height: 0vw;
}
Copy
これを加えるようにしてください。
clamp()のデメリット
タブレットデザインに柔軟に対応できない
タブレット付近はよしなに動いて貰う関数なので、もし
ゆうきくん
タブレットデザインでピクセルパーフェクトにならないんですけど!!
という場合は向きません。
しかし、私はそんな丁寧な現場に出会ったことが無いです。
強いていえば、タブレット時に柔軟に変化する仮定で他の要素とぶつかる可能性はあるので、そこは丁寧に検証する必要はあるかと思います。
まとめ clamp()の可能性は無限大!
基本的にclamp()はフォントサイズに使うことが一番多いですが、
- PCとSPデザインの数値が異なる
- PC~SPデザイン間はよしなに変化させたい
このような場合には、width、padding、marginなど幅広く使えるので、是非積極的に使ってみてください!
うまく使えれば、メディアクエリをわざわざ分けて書く機会が減ると思います。
また、clamp()を活用した関数なんかは、実はAIを使えばすぐに生成できます。
Web制作におけるChatGPTの使い方や、Cursorエディターの使い方を解説しているので、そちらも参考にしてください。
ちなみに、今回題材として動画で挙動をお見せしたのは、私が出しているデザインカンプからのコーディング練習課題の上級編になるので