display: flex
を利用してレスポンシブ対応のカードレイアウトを作りました。
アイテムの横幅、縦幅、アイテム間の余白(ガター)がいずれも相対指定のため、どんなウィンドウサイズでもバランスを崩すことのないレイアウトです。

⬇デモはこちらのcodepenでご確認いただけます。
実装の解説
詳しい実装はcodepenを見ていただきたいですが、ポイントとなる部分のみ記事にします。
この実装ではscssを利用しています。
横並びにする実装
.list {
display: flex;
flex-wrap: wrap;
}
カード全体を囲む.list
に対してdisplay: flex
を適用し、要素を横並びにしています。
アイテムとアイテム間の余白(ガター)の実装
&_item {
position: relative;
width: calc(100 / 430 * 100%);
$gutter: calc(10 / 430 * 100%);
margin: $gutter $gutter 0 0;
background-color: #ccc;
&:nth-child(4n) {
margin-right: 0;
}
}
position: relative
については後述しますので、ここでは気にしないでください。
アイテムのwidthをパーセント指定することでレスポンシブ対応しています。calcという関数を利用することで計算する手間を省いていますが、計算結果はwidth: 23.25%
となります。
※calcはプレーンなcssでも利用可能です。
ガターは、アイテムの上と右にmarginを指定することで実現しています。(marginの第一引数と第二引数)指定している値はcalcで計算した結果の変数$gutter
で、margin: 2.32% 2.32% 0 0
という出力になります。
marginをパーセントで指定すると、親要素の横幅に対する相対指定になります。margin-topであっても、親要素の縦幅ではなく横幅が基準となります。そのため、この実装ではmargin-topとmargin-rightは同じ幅になり、均一で常に綺麗なカードレイアウトになります。
⬇次にこちらの実装に注目です。
&:nth-child(4n) {
margin-right: 0;
}
すべてのアイテムにmargin-right: 2.32%
が適用されてしまうと右端のアイテムの右側にも余白がつき、1行に収まりきらなくなってしまうため、右端(4n個目)のmargin-rightを打ち消しています。今回のように、どんな画面幅だとしても4列を維持したい場合にぴったりの実装です。
アイテムが正方形を維持する実装
デモでは、アイテムはどんな画面幅であっても正方形の比率を維持します。
⬇以下にポイントとなるコードのみ記載します。
&_item {
position: relative;
&::before {
display: block;
content: '';
padding-top: 100%;
}
& > .text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
疑似要素before
内のpadding-top: 100%
がポイントです。paddingをパーセント指定すると、親要素の横幅が基準となります。したがってpadding-top: 100%
とすることで親要素の横幅と同じだけ高さを出すことができます。この方法を利用すれば、正方形以外にも2:3などアスペクト比を保持したレスポンシブレイアウトを作成することが可能です。
ただ、padding-top
は内側上部の余白ですので、このままアイテム内にコンテンツを配置すると余白の下に配置されるため正方形にはなりません。そこでアイテム内のコンテンツ.text
をposition: absolute
にして浮かせて、位置を上下左右中央寄せにしています。アイテムをposition: relative
にしているのはこのためです。こうすることで.text
の高さはアイテムに影響しなくなり、正方形の上に.text
が乗っているような状態となります。
まとめ
marginとpaddingをパーセント指定すると、親要素の横幅が基準となる点を利用したレスポンシブレイアウトをご紹介しました。わかりにくい仕様ですが特性を理解して活かすともっと柔軟なレスポンシブレイアウトが作れそうです。