【CSS】余白の指定に margin ではなく gap を使う

## はじめに
余白の指定を考えるとき、「ここでは margin を使う？それとも gap ?」と迷うことがあったため、どちらを使うのが良いのか？について考えてみました。

https://developer.mozilla.org/ja/docs/Web/CSS/margin

https://developer.mozilla.org/ja/docs/Web/CSS/gap

## 要素間に余白をつける

### 横に余白をつける

marginを使った書き方
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="mdozqOo" data-user="terakura-aina" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/terakura-aina/pen/mdozqOo">
  Untitled</a> by terakura-aina (<a href="https://codepen.io/terakura-aina">@terakura-aina</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

gap を使った書き方
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="yLwRPPM" data-user="terakura-aina" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/terakura-aina/pen/yLwRPPM">
  side-margin(margin)</a> by terakura-aina (<a href="https://codepen.io/terakura-aina">@terakura-aina</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


#### どちらを使うのが良いか
* gap では「最後の子要素以外に余白を適用する（`:not(:last-child)`）」といった指定をする必要がなく、シンプルに記述できるため、基本的には gap が良さそう
* 要素間の余白が異なる場合は margin で設定する必要がある

横並びにするときは基本的に `display: flex;` を使うと思います。
Grid や Flexbox では gap を使い、余白指定ができます。

margin での指定と見比べてみてもらうとわかるかと思いますが、gap では「最後の子要素以外に余白を適用する（`:not(:last-child)`）」といった指定をする必要がなく、要素間の余白を指定できるのでよりシンプルに書くことができます。

※ `display: flex;` は一部古いブラウザだと対応していなかったりすることもあり、以前は `float` を使って横並びを実現していたようですが、現在はほぼ全てのブラウザに対応しているようです。

### 縦に余白をつける

marginを使った書き方
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="gOEBXXV" data-user="terakura-aina" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/terakura-aina/pen/gOEBXXV">
  side-margin(margin)</a> by terakura-aina (<a href="https://codepen.io/terakura-aina">@terakura-aina</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

gap を使った書き方

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="LYagOOJ" data-user="terakura-aina" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/terakura-aina/pen/LYagOOJ">
  side-margin(gap)</a> by terakura-aina (<a href="https://codepen.io/terakura-aina">@terakura-aina</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### どちらを使うのが良いか
* gap では「最後の子要素以外に余白を適用する（`:not(:last-child)`）」といった指定をする必要がなく、シンプルに記述できる
* 要素間の余白が異なる場合は margin で設定する必要がある

↑に関しては横並びと同様です。

しかし縦並びのときにgap を使う場合、 margin を使う場合(margin-bottom で余白をつけるだけ)に比べると記述が多くなっています。
* `display: flex;` で Flexbox にする
* `flex-direction: column;` で縦並びにする
* その上で gap でやっと余白がつけられる

縦に並べたい場合、`display: flex;` を使わず margin をつけるだけで良いですが、gap を使うにはそのためだけに `display: flex;` を使う必要が出てきています。

この場合、margin を使うのが良いのか？と迷いますが、「そもそも余白は誰が知っているべき（制御すべき）なのか？」を考えたときに、gap を使う方が自然に感じました。

* margin を使った場合
  * margin は子コンポーネントにつく
  * 子コンポーネント自身が「自分は右側に 20px の余白を持つ」ということを知っていることになる
    * 自分より外側にも影響範囲が広がっている
* gap を使った場合
  * gap は親コンポーネントで制御する
  * 子コンポーネントは自分のスタイルを制御するだけで良くなり、自分の外側に影響を与えることがなくなる

「自分自身がどんな場面でも必ず余白を持つコンポーネントである」ということであれば、そのコンポーネント自身が margin を持つことは違和感がなさそうです。

ですが、最初に書いたコード例のように、要素同士が隣り合っているような場合、「子コンポーネント自身が意志を持って余白をつけている」というよりは「隣に要素が存在しているから、余白をつける」と考えるのが自然に感じます。（そして多くの場合がこちらに当てはまる気がする）

## 余白に Spacer コンポーネントを使う、という考え方もあるらしい
（若干 CSS からは脱線しますが余談です）

https://zenn.dev/seya/articles/09545c7503baa4#%E8%AA%B0%E3%81%AE%E6%8C%81%E3%81%A1%E7%89%A9%E3%81%A7%E3%82%82%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88

↑こちらの記事を参考にさせていただいていたときに存在を知ったのですが、余白をつけるための方法として、余白をつけるだけの Spacer コンポーネントを作成し、余白が必要な箇所でそのコンポーネントを置く、といったやり方もあるようです。

余白が親の制御ではなくなる、余白を入れるためだけの要素が増える、など気になる点もあるため、「どういう場所に Spacer を適用すべきなのか？」を考える必要はありそう :thinking: 

ただ、子コンポーネント自身の責務から余白をつける（自分より外側に影響を与える）、ということを外せるので、使い所はあるのかもしれない…詳しく調べたわけではないので、Spacer コンポーネントについてもちょっと調べてみたいなと思いました。

next.js にも Spacer というコンポーネントが用意されていそう :eyes: 

https://nextui.org/docs/components/spacer

## さいごに
最近 CSS を書く機会も増え、「あれ、これってどうなんだろう」と思ったことを自分なりに考えてみました。（まだまだ未熟者であるため、この記事で書いたことが正しいかは分かりません）

「ちょっと考え方が違いそう」「ここはこうなんじゃないかな？」と思うようなことがありましたら是非コメントで教えていただけると嬉しいです！

## 参考
https://developer.mozilla.org/ja/docs/Web/CSS/margin

https://developer.mozilla.org/ja/docs/Web/CSS/gap

https://zenn.dev/seya/articles/09545c7503baa4