CSSでレスポンシブにサイズを変える時、メディアクエリで画面幅にブレークポイントを指定するのではなく、
親要素のサイズにブレークポイントを指定して、親要素のサイズに応じて子要素のサイズを切り替える方法について。
なぜ画面幅でなく、親要素のサイズにブレークポイントを指定するのか
サイドメニューを250pxで画面左側に固定で作り、右側にコンテンツを配置するレイアウトとする。このようなレイアウトで、ボタンを押してサイドメニューを折り畳む機能を作ると、サイドメニューを表示した時はコンテンツの幅が縮小し、サイドメニューを折り畳んだ時はコンテンツの幅が広がる。
メディアクエリで画面幅にブレークポイントを指定してスタイルを切り替える場合、このコンテンツ幅の拡大縮小に対応できないので、今回のcalcを使ったサイズの切り替えが必要。
レイアウト
親要素の幅を800pxをブレークポイントとして、
- 親要素のサイズが799px以下 → 子要素の幅を100%にする
- 親要素のサイズが800px以上 → 子要素の幅を50%にする
また、サイズに応じて1列、2列の表示にする。
calcで親要素が指定の値を超えるか否かを判断
サイズを切り替えたい子要素に対して、下記のcssを記述。
min-width: 50%;
max-width: 100%;
width: calc((800px - 100%) * 800);
親要素が700pxの場合、calc((800px - 700px) * 800)
で8000pxとなり、max-widthより大きいので、max-width: 100%;
が適用される。
親要素が1000pxの場合、calc((800px - 1000px) * 800)
で-16000pxとなり、min-widthより小さいので、min-width: 50%;
が適用される。
あとは親要素に
display: flex;
flex-wrap: wrap;
を記述すれば、1列表示か2列表示かを切り替えられる。
HTMLとCSS
HTML
index.html
<!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>
<!-- style.cssの読み込み -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="side-menu"></div>
<div class="container flex">
<div class="card blue"></div>
<div class="card gold"></div>
</div>
</body>
</html>
CSS
style.css
body {
margin: 0;
}
.side-menu {
width: 250px;
height: 800px;
position: absolute;
top: 0;
left: 0;
background-color: brown;
}
.container {
margin-left: 250px;
height: 800px;
background-color: darkgrey;
}
.flex {
display: flex;
flex-wrap: wrap;
}
.card {
min-width: 50%; /* 親要素(container)が799px以下の時 */
max-width: 100%; /* 親要素(container)が800px以上の時 */
width: calc((800px - 100%) * 800);
height: 300px;
}
.blue {
background-color: cornflowerblue;
}
.gold {
background-color: goldenrod;
}