[CSS] marginとpaddingの使い分けに本気出してみた。が、borderもちゃんと考える。

# CSSの基本marginとpaddingについて学びます
Webコンポーネントを作成する際に、margin、paddingをどのように使い分けるかを考えてみました。

### ぼやき
Webコンポーネントを仕事で作る事が多いです。
コンポーネントをいかにいい感じにまるっとまとめるかを日々考えています。
当然それはスタイルの世界にも及びます。
HTML書いて、CSS書いて、JavaScript書きます。
CSSで、最近paddingとmarginの使い分けをちゃんとしようと思う事がありました。

**marginもpaddingも両方を利用している。確かに別にどっちでもいい。
だけど、なんか統一されていないと気持ち悪い。。。**

と言った感じです。
というわけで、少しまとめてみました。

# marginとpaddingについておさらい
## BOXモデルのどこの余白？
margin, paddingともにエレメントの外側に余白を作るスタイルです。
marginとpaddingでは余白を作る位置が違います。

たとえば、下記のようなエレメントを作成してみます。

```html
<body>
	<div></div>
</body>
```

```css+jinja
html, body {
	margin : 0;
	border : 0;
	padding : 0;
	width : 100%;
	height : 100%;

	background-color: #efefef;
}
body > div {
	display : inline-block;

	margin : 200px;
	border : 20px solid #7E57C2;
	padding : 20px;
	width : 120px;
	height : 120px;

	background-color : #FFA726;
}
```

表示は下記のとおりです。

![margin-padding-1.png](https://qiita-image-store.s3.amazonaws.com/0/83669/199a2f7d-4f6f-5392-3731-45275025cd83.png)

この画像の場合のmargin、paddingは下記のとおりです。（borderも登場します）

- margin 背景色がグレーの部分
- border 背景色が青の部分
- padding 背景色がオレンジの部分

これをGoogle chromeの開発者ツールで確認すると以下のようになります。
![image](https://qiita-image-store.s3.amazonaws.com/0/83669/423eb6bd-61b6-5732-0ac7-d1c77f452ee8.png)
背景色は
- margin 親のタグのbackground-colorになる(というよりかはmarginは透明の余白)
- border border用の色を決定できる
- padding エレメントに指定されたbackground-colorになる。
という感じになります。

そして、エレメントで保有したいサイズは、
width or height + padding + borderということになります。
※余談
レガシーブラウザでは、paddingはheightとwidthに内包されるものとそうでないものが存在していました。
とってもなつかしいです。
IE6あるあるです。

## どこまでをコンポーネントとして扱う？OOCSS的な。

エレメントのサイズが隣り合う要素や親要素に影響を与えるとコンポーネントは使いづらい。
配置構造や、コンポーネントとして作成したエレメントをどのように配置する？という事には、
干渉したくない！
となると、borderまでは作成するエレメントのboxのサイズとしてカウントしたい！
という感じになってきます。
ということで、サイズを指定する対象のエレメントに
`box-sizing: border-box`
を指定します。
すると、height、widthがエレメントのサイズとなり、
その中において、paddingとborderが表示される、ということになります。
※これはもしやIE6大正義だった！？

```css+jinja
/* すべてのタグのサイズをborder-boxに。 */
* {
	box-sizing : border-box;
}
```

![image](https://qiita-image-store.s3.amazonaws.com/0/83669/0a12c7a8-3e1f-38bf-7529-5bcdea2def10.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/83669/6f5822ba-7d5e-6b8f-5831-ca14a5ea7e40.png)
width、heightには120pxを指定していますが、実際はpaddingとborder分が引かれた値がwidth、heightに設定されています。
これは、コンポーネントを作成する際にとっても便利です。
**heightとwidthだけがそのコンポーネントで利用するサイズなんですよ！**
ということが明記出来ます。

だいぶスッキリできました。

## 縦配置の時のmargin

少しだけ脇道に逸れます。
marginについて少し理解を深めていきます。
コンポーネントを利用して、イカす感じで今風なレイアウトをします。
コンポーネントはwidthとheightがすべてで、marginがnoneな配置しやすいコンポーネントとします。
縦にコンポーネントを配置して、等間隔に並べていく・・・
あー、上下に16pxくらいmarginもたせればいいのかな。
ということは、エレメント1つあたりのmarignは8pxか。
という感じでやっていきます。

※画像ではわかりづらいので省略します。

するとどうでしょうか。
縦に隣接しているエレメントの余白は8pxしかありません。
marginは横marginに対しては、隣接するエレメントとは干渉しません。
しかし、縦に隣接するエレメント同士のmarginは干渉しあい、大きい方のmarginに合わさります。
隣接しているmarginがそれぞれ10px, 50pxの場合は、50pxのmarginになります。
ちょっとトリッキーな感じのmarginです。

# marginとpaddingの使い分けを考える

padding、marginをどのように使い分けるかを考えます。
コンポーネント化する際、一番大事なのは、**コンポーネントのルートエレメントが外の世界に影響を与えない。**
これは一番大事です。
つまり、**コンポーネントのルートエレメントにmarginはご法度**です。
ただし、前提として**Webコンポーネントを利用する環境では、すべてのエレメントは`box-sizing: border-box`であること**、というのが付いてきます。

鉄則はわかりました。
ではコンポーネントの中のエレメントの構造ではどうすれば良いのか。
両方使っていては、拡張性や保守性に欠けます。
最近は、SassやLessも良い感じに使われてきているので、自分しかメンテナンス出来なーいなんていうCSSは残したくありません。
これも実は簡単です。
**コンポーネントの中のエレメントの構造にもmarginは基本的に利用しないというのが鉄則**になると思います。
幅、高さのサイズの計算をwidth、height、padding、borderを含めた合算にしたくないから、`box-sizing: border-box`を指定しました。
にもかかわらず、marginを利用することで、また計算をしてしまっては本末転倒というもの。
なので、**余白を表現する際はpaddingを利用したい**と思います。

それではmarginはどこで利用するのか。
コンポーネントは外の世界に干渉をしません。
であれば、外の世界に干渉していいのは、コンポーネントを利用する人ということにしました。
つまり、**コンポーネントを利用し、レイアウトする時にコンポーネントにmarginを設定する**ということです。

# まとめ

- `box-sizing: border-box`を利用する。
- Webコンポーネントは基本的にpaddingのみで余白を表現する。
- Webコンポーネントを利用する人がmarginを使う。

まとめてみると意外とさっくりとしていました。
ということで、コンポーネント作成者である僕は迷わずpaddingを利用していきたいと思います。