「Webサイトのコーディングでどんな画面サイズでも崩れないレイアウトの作り方を知りたい」
「font-sizeはvwで指定するとレスポンシブ対応になるって本当?」
「clamp,max,minのそれぞれの使い分けがわからない」
本日はそんな方に向けて、CSSの新しいプロパティでwidthとfont-sizeをレスポンシブで指定する方法を共有します。
皆さんはWebサイトのレスポンシブ対応において、widthやfont-sizeをどのように指定していますか?
最近の新たな手法として、clamp、min、maxという便利なCSS関数が登場しました。
これらを駆使することで、要素の幅やフォントサイズをレスポンシブに調整することが可能です。
また動画でも解説しているので併せてご覧ください。
CSSのmin()とmax()でレスポンシブ対応をする使い方
まずはmin()とmax()の使い方から紹介していきます。
以下のようなHTML、CSSがあったとしましょう。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="container">
<div class="content">
<p>テストです</p>
</div>
</div>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 100%;
width: 600px;
height: 600px;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: 300px;
height: 300px;
background: #fff;
}
横幅600pxの黒四角のなかで横幅300pxの白四角が中央揃えで配置されています。
そこで黒四角はレスポンシブで画面サイズが小さくなっても、はみ出ないようにする場面はよくありますよね。
現状のCSSでもwidthと一緒にmax-widthを設定しているおかげでレスポンシブでも大きく崩れないようになっています。
これと同じようなことはwidthとmax-widthを削除してmin()だと以下のように書くことができます。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
/* ここを変更 */
width: min(600px, 100%);
height: 600px;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: 300px;
height: 300px;
background: #fff;
}
min()は関数になっていて第一引数と第二引数の値のうち、小さい方の値を採用するようになっています。
例えば1440pxの画面サイズだと600pxが採用されます。
これは100%の場合は1440pxになり、600pxと比べて小さい方を採用すると600pxになるからです。
一方で425pxの画面サイズだと425pxになり画面からはみ出ないように調整されています。
これは100%は425pxになり、600pxと比べて100%の方が小さくなるためです。
1行だけで簡単にレスポンシブ対応ができていて便利ですね。
細かくブレークポイントを刻みたい場合はメディアクエリを使って書くことになるのですが、PCとSPで分けるくらいのシンプルなレスポンシブであれば問題ないと思います。
続いてmax()も使ってみましょう。
HTMLとCSSを書き足して新しく同じようなマークアップを追加します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="container">
<div class="content">
<p>テストです</p>
</div>
</div>
<!-- ここを追加 -->
<div class="wrapper">
<div class="content">
<p>テストです</p>
</div>
</div>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
/* ここを変更 */
width: min(600px, 100%);
height: 600px;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: 300px;
height: 300px;
background: #fff;
}
/* ここを追加 */
.wrapper {
max-width: 100%;
width: 600px;
height: 600px;
margin: 0 auto;
background: #666;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .content {
width: 300px;
height: 300px;
background: #fff;
}
同じような要素を作りました。
こちらもwidthとmax-widthを組み合わせて画面サイズが小さくなってもはみ出ないようにしてあります。
widthとmax-widthを削除してmax()で書き換えてると以下のようになります。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: min(600px, 100%);
height: 600px;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: 300px;
height: 300px;
background: #fff;
}
.wrapper {
/* ここを変更 */
width: max(280px, 50%);
height: 600px;
margin: 0 auto;
background: #666;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .content {
width: 300px;
height: 300px;
background: #fff;
}
max()の場合は第一引数と第二引数を比べて大きい値を採用します。
min()とは逆の特徴になりますね。
メディアクエリもmax-widthと書くこともmin-widthと書くこともできるので同じことです。
例えば320pxの画面サイズの場合だと、50%が160pxになるので280pxと比べて大きい値である280pxを採用しています。
一方で1440pxの画面サイズだと50%が720pxになって、280pxと比べて大きい値である50%が採用されます。
こちらも1行でレスポンシブ対応ができて便利ですね。
min()とmax()は両方使えるようになるのがおすすめです。
CSSのclamp()でレスポンシブ対応をする書き方
今度はclamp()というCSS関数の使い方を紹介します。
HTML、CSSを新しく下記のように書き直します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="container">
<div class="content">
<p>
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
</p>
</div>
</div>
<div class="wrapper">
<div class="content">
<p>
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
</p>
</div>
</div>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 1400px;
width: 100%;
height: 600px;
margin: 0 auto;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: 600px;
height: 300px;
background: #fff;
font-size: 18px;
}
.wrapper {
width: 100%;
height: 600px;
background: #666;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .content {
width: 600px;
height: 300px;
background: #fff;
font-size: 18px;
}
まず上半分の「.container .content」についてですが、widthとmax-widthを使って画面サイズが小さくなっても白背景の四角が黒背景をはみ出ないようにしてあります。
「.container .content」のwidth: 600px;を削除してclamp()を使って以下のような書き方にしてみます。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 1400px;
width: 100%;
height: 600px;
margin: 0 auto;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
/* ここを変更 */
width: clamp(300px, 90%, 1000px);
height: 300px;
background: #fff;
font-size: 18px;
}
.wrapper {
width: 100%;
height: 600px;
background: #666;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .content {
width: 600px;
height: 300px;
background: #fff;
font-size: 18px;
}
画面サイズを変えても白背景の部分がはみ出ないようになっていますね。
clamp()は3つの引数を使って、「最小値、推奨値、最大値」という意味になります。
基本的には推奨値(第二引数)を優先しながら、画面サイズによって最小値(第一引数)と最大値(第三引数)をオーバーしないように自動でコントロールしてくれます。
「90%を基本にしながら小さい画面だと300pxを確保して、大きい画面では1000pxを上限にする」といった具合です。
1行だけでここまで出来ると相当効率的なコーディングですね。
clampは横幅だけでなく文字サイズにも使えます。
「.wrapper .content」のfont-size: 18px;を削除してclamp()を使って以下のように書いてみます。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 1400px;
width: 100%;
height: 600px;
margin: 0 auto;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: clamp(300px, 90%, 1000px);
height: 300px;
background: #fff;
font-size: 18px;
}
.wrapper {
width: 100%;
height: 600px;
background: #666;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .content {
width: 600px;
height: 300px;
background: #fff;
/* ここを変更 */
font-size: clamp(1rem, 1.25vw, 1.8rem);
}
基本的には推奨値(第二引数)の文字サイズで、画面サイズによって最小値(第一引数)と最大値(第三引数)をオーバーしないような文字サイズにしています。
例えば小さい画面だと16pxになります。
一方で大きい画面サイズだと18pxになります。
文字サイズもレスポンシブで調整が必要になりますよね。
メディアクエリを使わず1行で書けると非常に楽になるはずです。
少し古い方法で「vwを文字サイズに使うと1行でレスポンシブ対応になる」という説がありました。
「vw」は画面サイズによって自動で値を計算してくれるためです。
確かに理論的には合っているのですがデザインとしては好まれないことが多いです。
clamp()で書いたfont-sizeを以下のように書き換えてみてください。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
max-width: 1400px;
width: 100%;
height: 600px;
margin: 0 auto;
background: #333;
display: flex;
justify-content: center;
align-items: center;
}
.container .content {
width: clamp(300px, 90%, 1000px);
height: 300px;
background: #fff;
font-size: 18px;
}
.wrapper {
width: 100%;
height: 600px;
background: #666;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .content {
width: 600px;
height: 300px;
background: #fff;
/* ここを変更 */
font-size: 1.25vw;
}
「vw」にしたことで画面サイズによって文字サイズが変わっていくのがわかりますね。
作る側としては楽なのですが、実際に見る人の立場になると小さい画面だと文字が小さすぎて大きい画面だと文字が大きすぎます。
文字が大きすぎる分には良いかもしれませんが、小さすぎるのは流石に見た目が悪いです。
こちらもメディアクエリを使ってブレークポイントごとにfont-sizeを書き直せば解決するのですが、それならば「px」「rem」で良いことになり「vw」を使った意味がありません。
そんな痒い所に手が届くのがclamp()になります。
古いバージョンのブラウザだと動作しないのですが順次対応していくのでclamp()もぜひ使ってみてください。
またCSSの単位の違いについては以下の本でも解説されているので必要な方はご覧ください。