【超便利】CSS関数min()・max()・clamp()の使い方を解説!

【超便利】CSS関数min()・max()・clamp()の使い方を解説!

この記事を書いた人

もなか

30歳を過ぎてからプログラミングの勉強を独学で始め、現在コーダー3年目。毎日JavaScriptについて勉強中。趣味はパンを焼くこと。2人の男の子のママ。

CSSのプロパティにmin()max()clamp()という値があるのをご存知ですか?

これらのプロパティを使うと、メディアクエリ対応のために何行も書いていたコードが、たった1行に短縮できます!

当記事では、min()・max()・clamp()の概要や、min()・max()・clamp()の便利な使い方について解説します。

IEのサポートが終わったことで、モダンなCSSの情報収集している方は必見です!ぜひ最後までお読みください。

min()・max()・clamp()とは?

min()・max()・clamp()は、プロパティに設定する値を数式で計算するCSSの数学関数です

これらの関数を使うことで、メディアクエリを使わず、コンテンツベースなレスポンシブレイアウトを実現できます。

例えば、gridを使わない場合のリキッドレイアウトの幅指定に便利なcalc()も、CSSの数学関数のひとつです。

あわせて読みたい

こちらの記事ではcalc()を使った実装例を紹介しています。

>>【HTML&CSS】カード型レイアウト(モジュール)のコーディング方法

min()・max()・clamp()のブラウザ対応状況

引用:“min(), max() and clamp()” | Can I use…

現在はほとんどのモダンブラウザにサポートされています。すでにIEのサポートは終了していますので、どんどん使っていきたいですね!

min()とは

min()は二つの値を設定し、どちらか小さい方の値を値を表示します(=最大値が設定される)。

大きさの最大値を定義する時、今までだとmax-widthとwidthを組み合わせていたかと思います。

/* いままでの書き方 */
.box {
 width: 50vw;
 max-width: 600px;
}

しかし、min()なら同じ内容を1行で書くことができます。

.box {
  width: min(50vw, 600px);
}

カンマ区切りで1つ以上の値が設定でき、その中で最小の値が適用されます。

例1:viewportの長さ(100vw)が2000pxの場合

viewportが2000pxのときの動きの説明
viewportが2000pxのときの例

viewportの長さ(100vw)が2000pxのとき、50vwの長さは1000pxです。

つまり、(1000px , 600px)で比較されるため、600pxが適用します。

例2:viewportの長さ(100vw)が800pxの場合

viewportが800pxのとき動きの説明
viewportが800pxのときの例

viewportの長さ(100vw)が800pxのとき、50vwの長さは400pxです。

つまり、(400px , 600px)で比較されるため、400px(=50vw)のほうが適用します。

max()とは

max()は二つの値を設定し、どちらか大きい方の値を値を表示します(=最小値が設定される)。

大きさの最小値を定義する時、今までだとmix-widthとwidthを組み合わせていたかと思います。

/* いままでの書き方 */
.box {
 width: 50vw;
 min-width: 400px;
}

しかし、max()を使うと1行で実現できます。

.box {
  width: max(50vw, 400px); 
}

カンマ区切りで1つ以上の値が設定でき、その中で最大の値が適用されます。

例1:viewportの長さ(100vw)が1200pxの場合

max()のviewportが1200pxのとき動きの例
viewportが1200pxのときの例

viewportの長さ(100vw)が1200pxのとき、50vwの長さは600pxです。

つまり、(600px , 400px)で比較されるため、600pxが適用します。

例2:viewportの長さ(100vw)が700pxの場合

max()のviewportが700pxのとき動きの例
viewportが700pxのときの例

viewportの長さ(100vw)が700pxのとき、50vwの長さは350pxです。

つまり、(350px , 400px)で比較されるため、400pxが適用します。

clamp()とは

clamp() は、 min() と max() をあわせたような働きをします。

.box {
  width: clamp(最小値, 推奨値, 最大値);
}

カンマ区切りで(最小値 , 推奨値 , 最大値)の3つを指定し、その中の値から条件に合うものが適用されます

最小値
推奨値が最小値よりも小さくなると、要素の長さは最小値が適用されます。
最大値
推奨値が最大値よりも大きくなると、要素の長さは最大値が適用されます。
推奨値
要素の長さが最小値より大きく、最大値より小さいとき、要素の長さは推奨値が適用されます。
.box {
  width: clamp(400px, 50vw, 600px);
}

例1:viewportの長さ(100vw)が2000pxの場合

clamp()のviewportが2000pxのとき動きの例
viewportが2000pxのときの例

viewportの長さ(100vw)が2000pxのとき、推奨値である50vwの大きさは1000pxです。

つまり、(400px , 1000px , 600px)で比較されます。

このとき、推奨値(1000px)は最大値(600px)より大きくなっているため、最大値の600pxが適用されます。

例2:viewportの長さ(100vw)が700pxの場合

clamp()のviewportが700pxのとき動きの例
viewportが700pxのときの例

viewportの長さ(100vw)が700pxのとき、推奨値である50vwの大きさは350pxです。

つまり、(400px , 350px , 600px)で比較されます。

このとき、推奨値(350px)は最小値(400px)より小さくなっているため、最小値の400pxが適用されます。

clamp()の計算方法

以下コードの結果はどちらも同じ結果となります。

/* clamp */
.box {
  width:clamp(400px, 50vw, 600px);
}

/* min()・max()をあわせて使用した書き方 */
.box {
  width:min(600px, max(50vw, 400px));
}

clamp() は max() と min() をあわせて使用した場合と同じ動きをします。

min() と max() が組み合わさっていると難しく見えるかもしれませんが、ひとつひとつの動きを細かく見れば理解できるはずです。

実際に、viewportに具体的な数字を当てはめて計算してみましょう。

viewportが2000pxの場合

再度min()とmax()をおさらいしておきます。

min()
最大値を定義できる。1つ以上の値を設定し、その中で最小の値が適用される
max()
最小値を定義できる。1つ以上の値を設定し、その中で最大の値が適用される

ここではvewportが2000pxの場合を想定し、以下のコードを分解して解説していきます。

/* min()・max()を組み合わせた書き方 */
.box {
  width:min(600px, max(50vw, 400px));
}

max(50vw, 400px)の50vwは1000pxに置き換えられます。

/* 100vwが2000pxなので、50vwは1000px */
.box {
  width:min(600px, max(1000px, 400px));
}

/* max()関数の計算結果 */
.box {
 width:min(600px, 1000px);
}

max()は()内の最大値を適用するプロパティですので、1000pxと400pxを比較して、1000pxを採用します。

/* max()の計算結果をもとに、min()関数を実行 */
.box {
 width:min(600px, 1000px);
}

/* min()関数の計算結果 */
.box {
 width:600px;
}

min()は()内の最小値を適用するプロパティですので、1000pxと600pxを比較し、600pxを採用します。

以上のことから、viewportが2000pxの場合の長さは600pxと計算できます。

clamp関数が効かないときのチェックポイント

推奨値は固定値NG

clamp()が最小値と最大値の間の値を流動的に処理してくれるので、推奨値には固定値ではなく相対値(vw や %)を使用しましょう。

各種単位についての使い方やポイントは、こちらの記事で詳しく解説しています。あわせてチェックしてみてください!

Safariで効かないことがある

clamp()はSafariにもサポートされていますが、うまく計算してくれない事があるようです。

そんなときは以下のCSSを指定することで解決します。

/* Safariで効かないとき */
* {
    min-height: 0vw;
}

Sassでコンパイルエラーになる

Sassでmin()・max()・clamp()を使いコンパイルすると、以下のエラーが起きます。

Compilation Error
Internal Error: Incompatible units: 'vw' and 'px'.

この原因は、コンパイル時点で 1vw の値が確定していないため、固定値として出力できないからです。

このような場合、unquote()を使うと解決します。

unquote()は引用符を取り除いてくれるプロパティで、計算式をそのまま出力したいときに使えます。

//文字列としてそのまま出力させる
.box {
  width: unquote('min(50vw, 600px)');
}
/* 出力結果 */
.box {
  width: min(50vw, 600px);
}

()内でcalc関数のような数式指定

min()・max()・clamp()は、設定値に加算+減算-乗算*除算/の各演算子が使えます。

/* スペースを忘れずに! */
.box {
  width:max(100vw - 50vw, 400px);
}

演算子の両側には、必ず半角スペースが必要です。忘れずに入力しましょう。

各関数の使用例を紹介

モジュールの幅(width)

<div class="container">
  <div class="item"></div>
</div>
.container {
    max-width: min(85%, 800px);
}

上の例では.containerの幅が最大800pxとなるようにし、それ以下はブラウザ幅(body)に対して85%で表示させる指定になります。

ヘッダーナビゲーション間の余白(padding)

padding に max() を使うと、動的に余白の指定ができます。例ではheader の padding に max() を使用した例をご紹介しています。

.header {
  padding: max(12px, 2vw);
}

max()を指定したことで、動的な余白を設定しつつ、12pxは下回ることがないよう指定ができました。

動的に変化するテキスト(font-size)

clamp() を使うことでfont-sizeを可変させることも可能です。計算がしやすいよう、以下の基準でviewportの値を指定します。

  • モバイル=400px
  • タブレット=800px
  • PC=1200px
  .text {
    font-size:clamp(20px, 4vw, 40px) ;
  }
viewport 400pxの場合 ( 4vw = 16px )
4vwが最小値(20px)を下回っているので、このときのフォントサイズは20pxが適用されます
viewport 800pxの場合 ( 4vw = 32px
4vwは最小値(20px)と最大値(40px)の間にあるため、このときのフォントサイズは32pxが適用されます
viewport 1200pxの場合 ( 4vw = 48px )
4vwが最大値(40px)を上回っているので、このときのフォントサイズは40pxが適用されます

まとめ

今回はmin()max()clamp()の使い方を解説しました。

レスポンシブコーディングも、メディアクエリのみでCSSを書いてしまうとブレイクポイントが多発し、コードの見通しが悪くなってしまいます。

デバイスサイズを考慮しないモダンなCSSをマスターし、可能な限りメディアクエリに頼らないアプローチを身につけていけるとコーディングの幅が広がります。

この機会にぜひ導入検討してみてください!