clamp(◯rem, (100vw - ◯rem) * ◯, ◯rem) という構文でメディアクエリを使わずにレスポンシブ実装
私がレスポンシブなデザインを実装する際に、CSS のclamp()
関数を以下のように使って実装しています、という紹介です。
/*
画面幅が 30rem (480px) のとき 0rem で、
画面幅が 1rem 広がるごとに 0.2rem ずつ増えていくような値。
最大値は 10rem (160px)。
(画面幅が 80rem (1280px) のとき 10rem になる)
*/
.sample {
width: clamp(0rem, (100vw - 30rem) * 0.2, 10rem);
}
サンプルの CodePen を以下に示します。
ぜひ、「Edit on CodePen」からページを開いて画面幅を変えて試してみてください。
画面幅に応じて、要素の大きさが変化します。
どんなときに使う?
画面幅の拡縮に応じて、値を変化させたいときに使います。
- 画面幅が広いときはフォントサイズを大きく、狭いときは小さくしたい (
font-size
) - 画面幅が広いときは余白を増やし、狭いときは減らしたい (
padding
,margin
) - 人物の写真など、画面内に映る位置が重要な画像の表示位置を調整したい (
transform
,top
,left
など)
上記のように、PC/SP のように離散的に切り替えるのではなく、連続的に変化させたいときに使います。
このように連続的な変化を活用することで、メディアクエリ(@media (max-width: 768px)
など)を使わずに実装できます。
どうやって読む?
紹介した式は、 clamp(0rem, (100vw - <min-viewport-width>) * <slope>, <max-value>)
という形式の構文です。
最小値が 0rem
、最大値が <max-value>
で、画面幅が <min-viewport-width>
のとき 0 となり、そこから画面幅が広がるごとに <slope>
の傾きで値が増えていきます。
clamp(0rem, (100vw - 30rem) * 0.2, 10rem)
の値の変化を表したグラフを以下に示します。
どうやって書く?
次のことを決めます。
- 最小値をいくつにしたいか(
<min-value>
) - 画面幅がいくつのときに最小値にしたいか(
<min-viewport-width>
) - 最大値をいくつにしたいか(
max-value
) - 画面幅がいくつのときに最大値にしたいか(
max-viewport-width
)
このとき、<slope>
は (max-value - min-value) / (max-viewport-width - min-viewport-width)
となります。
例えば、以下のような場合を考えます。
- 画面幅が 30rem (480px) のとき 0
- 画面幅が 80rem (1280px) のとき 10rem にしたい
という場合、<slope>
は (10rem - 0rem) / (80rem - 30rem) = 0.2
となります。
.sample {
width: clamp(0rem, (100vw - 30rem) * 0.2, 10rem);
}
最小値を 0 以外に変えたいとき
最小の値を 0 以外の値にしたいときは、 <min-value>
の部分の値を変えてもいいのですが、そうすると計算がわかりにくくなるため、ここは 0rem
にしたまま、足し算してあげるのもよいです。
.sample {
width: calc(5rem + clamp(0rem, (100vw - 30rem) * 0.2, 10rem));
}
この場合、最大値も 5rem
増えることを考慮する必要があります。
clamp(◯rem, ◯rem + ◯vw, ◯rem)
との違いは?
clamp()
関数を紹介している記事では clamp(◯rem, ◯rem + ◯vw, ◯rem)
という形式の式を紹介していることが多いです(参考記事 1、参考記事 2)。
これとの違いは書き方のみです。 (100vw - 30rem) * 0.2
を展開すれば、 20vw - 6rem
となるので、結局のところ係数が違うだけです。
100vw
からの引き算で表現することで何が嬉しいかというと、いつ最小値になるのか読み取りやすくなることです。
◯rem + ◯vw
と書いてしまうと、どの画面幅でどの値になるのかわかりにくくなってしまい、メンテナンス性が下がります。100vw - ◯rem
と表現することで、ブレークポイントが ◯rem
であることがわかりやすくなります。
ただし、Sass 関数を用意したり、計算機を使うという選択肢もあるので、チーム内で管理しやすい方法を選択するとよいでしょう。
参考記事
Discussion