CSSの「calc」と「nth-child」を組み合わせて余白を意識した横並び

レスポンシブサイトでアイテムを横並びにする時のCSSの指定方法です。ウインドウサイズを変更したときに、ガタガタせずにスムーズに均等に縮めたりするには、CSSのcalc関数を使って余白を計算させながらパーセント指定すると、いい感じになります。

また、余白の制御でもう1つ使っていきたいのが、nth-childという疑似クラスです。改行手前のアイテムには余白を持たせないといったような処理ができるので、デザインカンプの再現度を高めることができます。

この記事では、calcnth-childを使った再現度の高いアイテムの横並び方法を紹介していきます。

はにわまん
calcはCSSで使える珍らしい演算関数です。

左右の余白はゼロ、間の余白が50pxのパターン

よくあるデザインカンプが以下のようにアイテムが並んでいて、左右の余白はゼロでアイテム間の余白だけが存在するパターンかと思います。

この例で一覧の作り方をみていこうと思います。横並びの方法としてはdisplay: flex;を使用します。

とりあえず、余白を無視してwidth: 33.33333333%;で並べた状態を作ってみます。margin:0;なので、びっちり詰まっていますね。

.items {
	display: flex;
	flex-wrap: wrap;
}

.item {
	box-sizing: border-box;
	border-radius: 8px;
	box-shadow: 0 0 5px rgba(17, 51, 72, 0.2);
	color: #3c3c3c;
	margin: 0;
	padding: 20px 20px 22px 20px;
	text-decoration: none;
	transition: all 0.3s ease 0s;
	width: 33.33333333%;
}

1、余白のmarginを指定する

今回は、アイテム間の余白が50pxなので、とりあえずmargin: 0 50px 50px 0;を指定してみます。右と下に50pxを余白をつけるといったものですね。

.item {
	margin: 0 50px 50px 0;
}

カラム落ちしてしまいました。カラム落ちとは、横幅に入りきらないから下に改行されてしまっている状態ですね。

これは、それぞれの.itemが持っている横のサイズが、33.33333333%(width) + 50px(margin-right)となっているためですね。横幅は33.33333333%ですでに限界なので、50pxがそれぞれのアイテムに付いたことで溢れてしまっている状態です。

2、溢れないように50px分を引いてみる

ここでcalc関数の登場です。calcの優れているところはパーセントと固定値でも計算できる点にあると思っています。

.item {
	margin: 0 50px 50px 0;
	width: calc(33.33333333% - 50px);
}

カラム落ちがなくなりました!!!

ただし、まだ問題があります。それは、3つ目のアイテムにもmargin-right: 50px;があることで、左右がピッタリ合わないということです。

3、○個目のアイテムの余白は0px、かつ間の余白も調整

まずは、○個目のアイテムの余白は0pxにするという指定を入れてみます。利用するCSSはnth-child()という疑似クラスです。これは、○個目のアイテムに対する処理を指定できるものになります。

3の倍数で処理を当てたいので3nとして以下のように指定します。

.item:nth-child(3n) {
    margin-right: 0;
}

続いて、アイテムの幅を調整します。必要な余白は3つのアイテムの間にある50pxと50pxになります。合計すると100pxです。

この100pxを3つのアイテムに均等に分け与えてあげると、100px / 3 = 34px(小数点以下を切り上げ)になります。それぞれの33.333333%から34pxを引いてあげれば、余白は常に一定だけをアイテムは可変にすることができます。

.item {
	margin: 0 50px 50px 0;
	width: calc(33.3333333% - 34px);
}

もしくは、以下のような書き方でもいいかもしれません。

.item {
	margin: 0 50px 50px 0;
	width: calc(33.3333333% - 100px / 3);
}

間の余白が50pxで他は均等にレスポンシブ化されているのが分かります。

4、幅に応じて余白を変更する

どの幅でも50pxの余白だととても不格好です。やはりウインドウ幅が小さくなれば応じて余白も小さくしていかなとバランスが取れません。

例えば、ある一定の幅以下になったら余白は30pxにするとします。アイテムの幅の計算方法も上記と同じで、30pxの余白が2つで60px。これを3つのアイテムで割る、ということを行えばOKです。

@media screen and (max-width: 1179px) {
	.item {
		margin-right: 30px;
		width: calc(33.3333333% - 60px / 3);
	}
}

幅に応じで余白が変わっているのが分かるかと思います(アイテムは3等分)

5、表示する列数を変える場合はnth-childの場所も変える

今はずっと3列にしていますが、表示する列の数を変えたい場合は、nth-child()の値を変えないと、余白の間隔がおかしくなります。

1179px以下では2列にする場合は以下のような感じになります。※ 最低限のプロパティしか書いていません。

.item {
	margin: 0 50px 50px 0;
	width: calc(33.3333333% - 100px / 3);
}

.item:nth-child(3n) {
	margin-right: 0;
}

@media screen and (max-width: 1179px) {
	.item {
		width: calc(50% - 50px / 2);
	}

	.item:nth-child(3n) {
		margin-right: 50px;
	}

	.item:nth-child(2n) {
		margin-right: 0;
	}
}

3カラムと2カラムがスムーズに違和感なく移り変わっているのが分かるかと思います。

こんな感じで、カラム数とレスポンス時の対応によってnth-childwidthの値を余白のとり方によって変動させていくといい感じになるかと思います。

おわり


widthnth-childを活用して余白を意識した横並びの方法でした。ここまで厳密に計算する必要があるかどうかは案件次第かもしれませんが、デザインカンプからちゃんと再現しようと思ったときに、この書き方が自分の中で一番しっくり来たので今のところ採用しています。

(他にいい感じのやり方があったら教えてください><)

このページが役に立ったら
いいね!お願いします

運営の励みになります...。

関連の記事