marginとpaddingの違いを本気で解説してみた

## はじめに

block 要素に `margin` と `padding` をそれぞれつけてみるとどうなるか。

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="EaYzNxN" data-pen-title="Untitled" data-user="KadoProG" 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/KadoProG/pen/EaYzNxN">
  Untitled</a> by KadoBloG (<a href="https://codepen.io/KadoProG">@KadoProG</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

見ての通り、両者とも左側に同じ余白が挿入されており、この時点では特に違いがない。

そんなとき、あなたは迷ったらどちらを使うだろうか？

## marginは外側、paddingは内側に余白が発生

まず結論を言うと、要素に対して**marginは外側、paddingは内側**に余白が発生する。

:::note info
直訳すると、`margin`は、**余白,欄外,余地**という意味合いがあり、一般的な余白の使い方に近い。一方、`padding`は、**詰め物,芯**という意味合いがあり、コンテンツの中に埋め物をするイメージである。
:::

## 外側、内側による余白の仕様の違い

では、外側、内側という違いにより具体的に何が違うのかを解説する。

### CSSスタイルの範囲

![paddingとmarginの違い2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/80cf8722-f0b3-6d78-fca3-858d2d10df88.png)

- 背景
- ボタンやアンカーリンクのクリック範囲
- borderの囲い
- 要素サイズ(width, height)に含まれるか
  - box-sizingにより変化

`margin`は上記に上げた項目には一切関わらない。逆に、`padding`はこれらの影響を受け、背景・ボタンの範囲を制御できる。

|margin|padding(デフォルト)|
|-|-|
|![スクリーンショット 2025-02-04 5.54.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/49b95dfc-366e-f7b4-d949-4e65bd7b3012.png)|![スクリーンショット 2025-02-04 5.54.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/640efbb1-66af-c02f-5691-6e0c50f32ac8.png)|

Qiitaのボタンは良い例で、現状仮にこれをmarginでやった場合と比較するとこうなる。

marginで実施すると、背景及びクリック範囲がかなり縮小しているのがわかる。ただし余白自体はかかっているため、表示位置は両者一緒。

### 隣同士の余白の取り扱い

![スクリーンショット 2025-02-04 5.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/3dea98f6-f658-ef3f-4282-090fb005ce9b.png)

次に、隣同士の余白の取り扱いの違いだ。試しに、左の要素には右に余白30px, 右の要素には左に余白10pxを与えてくっつけると仮定する。

![スクリーンショット 2025-02-04 8.40.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/60fc357e-f8f1-3fdf-82c0-745cd74ccb8e.png)

実際に `flex`等でくっつけると、**marginでは10px分が重なって30pxの余白となっている**。逆に**paddingは単純に加算され余白は40px**となる。


### marginは指定した最低限の距離を開ける

![スクリーンショット 2025-02-04 6.26.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/ed7ab126-800b-744b-d60b-5abbeb6367fb.png)

marginの概念について、人で例えると分かりやすい。`10cm`と`2m`(200cm)の~~社会的~~距離を担保したい人（HTML要素）がある場合、**200cmが優先され、10cmは実質無視**される。それがmarginである。

![スクリーンショット 2025-02-04 6.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/bf17cd3d-4b6b-0766-33a4-3f55e456eba4.png)

ただし例外もあり、**marginはマイナスの値が可能**で、`-2m`, `2m`であれば実質0mとなり、更にマイナスの値を大きくすると、要素が重なる。

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="bNbyBey" data-pen-title="padding-first-code-2" data-user="KadoProG" 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/KadoProG/pen/bNbyBey">
  padding-first-code-2</a> by KadoBloG (<a href="https://codepen.io/KadoProG">@KadoProG</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

通常のWebアプリで使用されることはほぼないが、LPデザインで特殊な実装をする場合使うことがある。

### paddingは優等生

一方`padding`は、繰り返しになるが**内側に余白が発生するため、外的要因を受けない**。マイナスの値も適用できない。

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="raBgjzK" data-pen-title="padding-first-code-5" data-user="KadoProG" 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/KadoProG/pen/raBgjzK">
  padding-first-code-5</a> by KadoBloG (<a href="https://codepen.io/KadoProG">@KadoProG</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

`padding`は背景を適用されるため、シンプルなボタンの装飾に非常に便利だ。また、**コンテナ側にも`padding`を適用**している。

:::note info
コンテナ側に`padding`を付与すると、子要素側に`margin`等を付ける必要がないため、再利用性が非常に高く、実装が容易になる。
また、`display: flex`、`justify-content: space-between` を付与すれば、横並び、かつ横の余白を自動調整してくれる。
![スクリーンショット 2025-02-04 10.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/efbdac44-71dc-066c-9518-d82372c140c8.png)
:::

## 結局どちらを使用すべきか

極論言ってしまうと、余白は**paddingだけで実装が可能**であるし、逆に`margin`だけでも実装が可能である。

しかし、実際にコードを見ると、**実装のしやすさで`padding`が使いやすい**と言える。

#### paddingは潔い

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JoPqEZq" data-pen-title="padding-first-code-7" data-user="KadoProG" 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/KadoProG/pen/JoPqEZq">
  padding-first-code-7</a> by KadoBloG (<a href="https://codepen.io/KadoProG">@KadoProG</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

もし仮に全て`margin`でやる場合、`button`の中に`span`要素を付与し、そこに`margin`を付与すれば、同じボタンを実装できる。

ちなみに`padding`の場合は`button`に`padding: 20px`だけで完了する。潔い。

### 全体のレイアウト調整はmarginを使ってはいけない

|marginのみ|![スクリーンショット 2025-02-04 13.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/d76a0da4-97d9-a9f6-9794-b1e2aaff617b.png)|
|-|-|
|paddingとflex|![スクリーンショット 2025-02-04 13.04.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/753538ed-13a8-8986-d7fc-2df5ee23c430.png)|

横並びで、間に余白があるレイアウトを実装する場合、`margin`で実装するのは現実的じゃない。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YPKbZBr" data-pen-title="padding-first-code-8" data-user="KadoProG" 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/KadoProG/pen/YPKbZBr">
  padding-first-code-8</a> by KadoBloG (<a href="https://codepen.io/KadoProG">@KadoProG</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

固定サイズでは`margin`, `padding`とも同じレイアウトを維持している。
しかし、Webサイトは異なる横幅に対応させる必要があるため、`margin`を使用した場合、これ以外のサイズで表示が崩れる（チェックボックス押してプレビュー）。
ブラウザ・コンテナの横幅だけでなく、中の要素も**1pxでも変更されれば、再び`margin`の変更**が必要である。

対して`padding＆flex`の方は、全く崩れることはない。上下は`padding`で実装し、横の隙間は`flex, justfy-content: space-between`で実装可能だ。何より、コード量が`padding`のほうが少ない。

:::note info
`flex`の並び方は複数あるので、色々調べてみるのがオススメ！

もし先程の`margin`と同様に一定間隔を開けたい場合は、`gap`を使用すると最低限の距離を開けつつ、コンテナ要素が自動的にサイジングされる！
:::

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

### シンプルな実装はmarginでもOK

![スクリーンショット 2025-02-04 11.19.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/2f01766f-dbdf-8bfd-c388-3138d42a751a.png)

WordPressで構成されたブログは、段落で`margin-bottom`が使用されている。`margin`は、上下左右のみの付与も可能で、下部のみであれば、前述した`margin`重なり問題が発生しないため、直感的に実装できる。

### marginで中央寄せ可能

![スクリーンショット 2025-02-04 14.49.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/2750f541-2f8e-ebcf-9fd0-9ccc8dd090b9.png)

`margin: 0 auto;`(最初の0は上下の余白)のように指定をすることで、中央寄せが可能である。
ただし、その要素が**block要素で、親要素より小さいサイズ**を指定する必要がある。簡単なようで実は難しい。
また、単にテキストを中央寄せしたい場合は`text-align: center`を使用する方法もあるし、横並びで複数表示するときは`flex`を使用する方法もある。

### marginは細かい実装には不向き

ブログのように比較的統一されているレイアウトの場合、上記の実装で十分である。しかし、Webアプリなど、複雑な実装を必要とする場合、場所によって`margin`が異なる。

|通常|入れ替え|
|-|-|
|![スクリーンショット 2025-02-04 11.10.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/105f5324-b8bc-e3cf-7edd-c517deed18f7.png)|![スクリーンショット 2025-02-04 11.13.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/bae5f144-0b4e-17ed-13d8-7c7c9b283bd0.png)|

例えば、「送信しますか？」のスタイルには、`margin-top: 20px; margin-bottom: 0`を指定している。
しかし、中のレイアウトが入れ替わると、それだけで**コンテナ内のCSSは全て書き換える**必要がある。

## 可能な限りpadding, flex-boxを使用しよう

簡単な実装でない限りは、padding, flex-boxを使用することが無難となる。とはいえ実際のサイトがどうなっているかは、実際に見てみるのがオススメ。

Chromeであれば `Ctrl/Cmd` + `Shift` + `C` で、要素の選択ができる画面となる。そこで、実際のHTMLがどのように余白表示されているか検証してみると良い。

[某X](https://x.com) や[ChatGPT](https://chatgpt.com/)は、ほぼ`padding`及び`flex`で構成されている。

![スクリーンショット 2025-02-04 14.57.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538408/f85e7196-bb28-cd9e-96ff-c8f3ba519878.png)

要素は青、`margin`はオレンジ、`padding`は緑で閲覧できる。flex-boxの場合、紫の斜め線で閲覧できる。

## 参考記事

https://qiita.com/otsukayuhi/items/d88b5158745f700be534