【CSS】暑いのでチョコモナカ作りましょう

こんなデザインをよく見かけると思います。

![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/0cdf15e1-2ee7-3eff-1d5e-1980eb529019.png)

チョコモナカのように要素を並べるこのデザインですが、よりスマートに実装するにはどうすればいいでしょうか。

以下のようなHTMLがあるとします。

~~~html
<body>
	<section class="wrapper">
		<header class="title">
			コンテンツ領域
		</header>
		<ul class="monaka">
			<li class="monaka-el">
				<div class="monaka-content">要素</div>
			</li>
			<li class="monaka-el">
				<div class="monaka-content">要素</div>
			</li>
			<li class="monaka-el">
				<div class="monaka-content">要素</div>
			</li>
			<li class="monaka-el">
				<div class="monaka-content">要素</div>
			</li>
			<li class="monaka-el">
				<div class="monaka-content">要素</div>
			</li>
		</ul>
	</section>
</body>
~~~

![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/a2f20375-e0eb-fa2c-b2d4-9e83736d2285.png)

上記コードをそのまま表示するとこんな感じ。これにスタイルを当てて、チョコモナカ的な形にしていきましょう。

## 推奨されるやり方3選

### ネガティブマージンとflexを使う

~~~css
<style type="text/css">
.monaka {
	display: flex;
	flex-wrap: wrap;
	margin: 0 -15px;
}
.monaka-el {
	flex: 0 0 50%;
	padding: 15px;
}
</style>
~~~

![image-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/ff263874-924c-5002-4c79-9dd226eacc72.png)

bootstrapでも使用されている、由緒正しい実装です。paddingを使って各要素のスペースを均等に取り、左右の隙間を親要素のネガティブマージンで埋めます。

marginの値にマイナスを指定することで、親要素からはみ出した子要素を作ることが出来ます。ネガティブマージンは大変便利なので、ぜひ使い方を覚えてください。

### Gridを使う

最もモダンなやり方です。

**グリッドレイアウトの基本概念 – CSS – MDN Web Docs**
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout

~~~css
<style type="text/css">
.monaka {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 30px;
}
.monaka-el {
}
</style>
~~~

万能ですが、モダンすぎて実装されていないブラウザがあるところは欠点でした。最近は動かないブラウザもほぼ無くなりましたので、業務で使用することも概ね可能です。グリッドレイアウトは様々なデザインに対して柔軟に使用できますので、このチョコモナカだけでなく色々な使い方を探してみてください。

### justify-content: space-betweenを使う

flexの機能だけでなんとかすることもできます。

~~~css
<style type="text/css">
.monaka {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
}
.monaka-el {
	margin: 15px 0;
	flex: 0 0 calc(50% - 15px);
}
</style>
~~~

![image-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/692db356-367a-8ac6-e69f-dbef2584df76.png)

flexの機能で完結しているので、CSSの可読性は高いかもしれませんね。ただし、3列のチョコモナカを作ったりする際に、最後の行に入る要素が2つだったりすると、以下のような変な見た目になったりします。

![image-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/bc8beea6-1912-c074-c6bd-6454778d837f.png)

使いどころは注意してください。

## flexを使う際に*やってはいけないこと*

上のGridレイアウトの際に使用したgapプロパティですが、一見Flexレイアウトにも使用出来そうに見えます。

~~~css
<style type="text/css">
.monaka {
	display: flex;
	flex-wrap: wrap;
	gap: 30px;
}
.monaka-el {
	flex: 0 0 calc(50% - 15px);
}
</style>
~~~

これはGoogle Chromeでは機能しますが、Safariで機能しない場合があります。

**Flexboxでgapは使える？ブラウザ（IE・Safari）対応状況について**
https://pengi-n.co.jp/blog/flexbox-gap/

iOS14以下で動作しない場合がありますので、flexに対してgapプロパティを使うのはやめましょう。

### いにしえの手法
#### floatを使う

~~~css
<style type="text/css">
.monaka {
	margin: 0 -15px;
}
.monaka::after {
	content: "";
	display: block;
	clear: both;
}
.monaka-el {
	float: left;
	margin: 15px;
	width: calc(50% - 30px);
}
</style>
~~~

floatプロパティを使って、要素を横並びにすることでチョコモナカを実現しています。

floatプロパティは、もともと対象の要素に対してテキストなどがどう回り込むかを指定するプロパティでした。

![image-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/03d7cc2d-dd5f-034a-929f-9381016bf71a.png)

floatが指定された要素が複数並ぶとそれらが横並びになる性質を利用し、要素を横並びにする際に昔よく使われていました。親要素のafterに[clearfix](https://web-camp.io/magazine/archives/27842)と呼ばれるおまじないを書かなければデザインが崩れてしまうことも覚えておきましょう。

現在はflexがあるのでそちらを使いましょう。

#### `display: inline-block`を使う

~~~css
<style type="text/css">
.monaka {
	margin: 0 -15px;
	font-size: 0;
}
.monaka-el {
	font-size: 16px;
	display: inline-block;
	margin: 15px;
	width: calc(50% - 30px);
}
</style>
~~~

要素をinline-blockにすることで横並びにする手法です。inline-blockは文字列などのinline要素と同じ性質をもつようになるので、勝手に横並びになります。

ただし、横並びにした際に文字と文字の間に入るスペーシングも適用されてしまうので、横幅がぴったり収まらなくなります。これは親要素のfont-sizeを0にすることで回避できますが、子要素で再度font-sizeを指定してやる必要があるのでちょっと面倒です。

現在はflexがあるのでそちらを使いましょう。

#### 左にくる要素と右にくる要素で当てるスタイルを変更する

~~~css
.monaka {
	display: flex;
	flex-wrap: wrap;
}
.monaka-el {
	margin: 15px 0;
	width: calc(50% - 15px);
}
.monaka-el:nth-of-type(odd) {
	margin-right: 15px;
}
.monaka-el:nth-of-type(even) {
	margin-left: 15px;
}
~~~

ネガティブマージンを使用しなくてもチョコモナカが実現できますが、急なデザイン変更に対応しづらいのでやめましょう（3列にする必要が出た時とか）。ソースも可読性が低くなる印象があります。

---

以上、6つほど手法を紹介しました。こういった横並びの要素を作る方法はCSSの歴史の中で多数出現してきました。

現在はflexを使う手法が基本になっています。その上でネガティブマージンのテクニックを使用することで、綺麗なソースでチョコモナカの配置を実現することができます。今後はgridが流行っていく予感もしますが、既存の手法を覚えておいて損になることはないでしょう。

他にチョコモナカを実現する面白い手法をご存じの方がいましたら、是非コメントで紹介してください。