UIコンポーネントにはマージンをつけるな！絶対にだ！！

私は長年、`CSS`の`margin`をどのように書くか悩んできました。

たとえば、このようなボタン。

```html

<button class="button">ボタンだよ</button>
```

```css

.button {
  display: block;
  margin: 50px auto 0;
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="QWLMQRJ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="button_01">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/QWLMQRJ/">
  button_01</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

パット見、いい感じのボタンです。

しかし、このボタンには一点重大な欠点があります。

それは、**このボタンは必ず上に50pxの余白が付き、かつ中央寄せされる**ということです。

## デザイナー登場

デザイナーがこう言いました。

**「ボタンを横に２つ並べたい」**
**「ボタンとボタンの間隔は20px」**
**「その上で中央寄せで！」**
**「あと、上のマージンは外しといて！」**

さて、どうしましょう？？`display: flex;`でしょうか？

```html
<div class="flex">
  <button class="button">ボタンだよ</button>
  <button class="button">ボタンだよ</button>
</div>
```

```css
.flex {
  display: flex;
}

.button {
  display: block;
  margin: 50px auto 0;
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="qBWXoWa" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="qBWXoWa">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/qBWXoWa/">
  qBWXoWa</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

。。。どうやら、`.button`から`margin: 50px auto 0;`を削除しないことには無理そうです。。

しかし、このボタンはすでに別のページで使われており、`margin: 50px auto 0;`を削除すると、**様々なページのボタンから上の余白と中央寄せが失われてしまいます。**

これは非常にまずい！

影響がないように、`.row-button`をつくりましょうか。

```html

<div class="row-buttons">
  <button class="row-button">横並びボタンだよ</button>
  <button class="row-button">横並びボタンだよ</button>
</div>
```

```scss

.row-buttons {
  display: flex;
  justify-content: center;
}

.row-button {
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
	
  &:nth-child(n+2) {
    margin-left: 20px;
  }
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="OJLjvyE" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="OJLjvyE">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/OJLjvyE/">
  OJLjvyE</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

なんとか難は逃れたようです。よかったよかった。

## デザイナー再登場

**「縦に20pxの間隔で積まれたボタンが必要です」**

な、なんだと。。。

```html
<div class="column-buttons-container">
  <div class="column-buttons">
    <button class="column-button">縦並びボタンだよ</button>
    <button class="column-button">縦並びボタンだよ</button>
  </div>
</div>
```

```scss

.column-buttons-container {
  display: flex;
  justify-content: center;
}

.column-buttons {
  display: inline-flex;
  flex-direction: column;
}

.column-button {
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
  
  &:nth-child(n+2) {
    margin-top: 20px;
  }
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="pozrLbX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="flex column button">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/pozrLbX/">
  flex column button</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

だんだんいい感じになってきましたね！＼(^o^)／

## `.button`にマージンがなければ問題なかった

もうお気づきかと思いますが、`.button`がマージンを持っていなければたくさんのボタン用CSSクラスは不要でした。

```html

<button class="button">ボタンだよ</button>
```

```css

.button {
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
}
```

### 単体中央寄せ

```html

<div class="centering">
  <button class="button">中央寄せボタン</button>
</div>
```

```css

.centering {
  display: flex;
  justify-content: center;
  margin-top: 50px;
}

.button {
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="PoYKRWB" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="中央センタリング上マージン">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/PoYKRWB/">
  中央センタリング上マージン</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### 横並び中央寄せ

```html
<div class="row-buttons">
  <button class="button">横並びボタン</button>
  <button class="button">横並びボタン</button>
</div>
```

```scss
.row-buttons {
  display: flex;
  justify-content: center;
	
  > *:nth-child(n+2) {
    margin-left: 20px;
  }
}

.button {
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="bGbrvqO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="横並び中央寄せ">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/bGbrvqO/">
  横並び中央寄せ</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### 縦積み

```html
<div class="column-buttons-container">
  <div class="column-buttons">
    <button class="button">縦積みボタン</button>
    <button class="button">縦積みボタン</button>
  </div>
</div>
```

```scss
.column-buttons-container {
  display: flex;
  justify-content: center;
}

.column-buttons {
  display: inline-flex;
  flex-direction: column;
	
  > *:nth-child(n+2) {
    margin-top: 20px;
  }
}

.button {
  padding: 8px 20px;
  border: solid 2px #ddd;
  border-radius: 10px;
  font-size: 16px;
}
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="css,result" data-user="boltkeep" data-slug-hash="yLBoKXL" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="yLBoKXL">
  <span>See the Pen <a href="https://codepen.io/boltkeep/pen/yLBoKXL/">
  yLBoKXL</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

クラス名がダサいのはご容赦願います＼(^o^)／

## まとめ

今回は`button`のみの例でしたが、ほかの要素やUIコンポーネントでも**ページによってマージンが違ったりするスタイル**はよくあるかと思います。

デザインに柔軟に対応するためにも、**UIコンポーネントにはマージンを持たせず、使う側から指定してあげる**というルールを設けてあげれば、CSSが少し楽になるかもしれません。

もちろん、例外は存在しますので、例えばLPとかで**そのUIにはこのマージンしか絶対に存在しない**みたいなことがあれば、直接書いても良いかと思います。

それでは、また。