- CSS
CSS marginとpaddingの違い|相殺と効かない原因一覧
margin は要素の「外側」の余白、padding は要素の「内側」の余白です。境界線(border)を挟んで、外にあるのが margin、内にあるのが padding で、背景色が塗られるのもクリックに反応するのも padding まで、という違いがあります。 もうひとつ大きな違いが、上下の margin 同士は重なって1つにまとまる「相殺」が起きるのに対し、padding では起きないことです。
この記事では、ボックスモデルの図と違いの比較表、1〜4値の書き方と論理プロパティ(margin-inline / margin-block)、相殺が起きる3パターン(兄弟・親子・空要素)、相殺しない条件、「効かない」ときの原因チェック表と解決策、gap との使い分けまでを扱います。寸法はすべて Chromium 141(Playwright 1.56 のヘッドレス実行)で getBoundingClientRect() と getComputedStyle() を使って実測しました。 「30px と 20px の margin が並ぶと間隔は何 px か」を、数値で確かめながら読めます。
marginとpaddingの早見表
| 比べる点 | margin(外側の余白) | padding(内側の余白) |
|---|---|---|
| 位置 | border の外側 | border の内側(中身と border の間) |
| 背景色・背景画像 | 塗られない(常に透明) | 塗られる |
| クリック・ホバーの反応 | 反応しない | 反応する(要素の一部) |
| 負の値 | 指定できる(-10px で要素を重ねたり引き寄せたりできる) |
指定できない(無効になり、0 のまま) |
auto |
指定できる(余った幅を自動で割り当てる。中央寄せに使う) | 指定できない(無効) |
| 上下の相殺 | 起きる(大きいほうだけが残る) | 起きない(そのまま足される) |
width・height への影響 |
含まれない | content-box(既定)では外に足され、border-box では内に含まれる |
% の基準 |
親の幅(上下の指定でも幅が基準) | 親の幅(同じ) |
| インライン要素の上下 | 効かない | 背景は広がるが、行の高さは変わらない |
| 主な用途 | 要素と要素の間隔、中央寄せ | 中身と枠の間隔、クリックできる範囲を広げる、背景を広げる |
迷ったら「背景色を付けたときに、色が付いてほしい部分は padding、付いてほしくない部分は margin」と考えると選びやすくなります。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS marginとpaddingの違い|相殺と効かない原因一覧」
ボックスモデルで見るmarginとpaddingの位置
CSS では、すべての要素が4層の箱(ボックスモデル)として扱われます。内側から順に、content(中身)、padding、border、margin です。
┌───────────────── margin(外側の余白・透明)──────────────────┐
│ │
│ ┏━━━━━━━━━━━━━━ border(境界線)━━━━━━━━━━━━━━━┓ │
│ ┃ ┃ │
│ ┃ ┌────────── padding(内側の余白)──────────┐ ┃ │
│ ┃ │ │ ┃ │
│ ┃ │ content(文字や画像が入る領域) │ ┃ │
│ ┃ │ │ ┃ │
│ ┃ └──────────────────────────────────────────┘ ┃ │
│ ┃ ↑ ここまで背景色が塗られ、クリックに反応 ┃ │
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │
│ │
└──────────────────────────────────────────────────────────────┘
背景色とクリック領域を実測する
width: 100px; height: 40px; padding: 20px; margin: 30px の青い div を置き、スクリーンショットの色と、クリックへの反応を調べました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<style>
body { margin: 0; }
#t {
width: 100px; height: 40px;
padding: 20px;
margin: 30px;
background: rgb(0, 128, 255);
}
</style>
</head>
<body>
<div id="t" onclick="console.log('クリックされました')"></div>
</body>
</html>
| 調べた位置 | その場所 | 画面の色 | クリック |
|---|---|---|---|
| (80, 80) | content | 青 rgb(0, 128, 255) |
反応する |
| (40, 40) | padding | 青 rgb(0, 128, 255) |
反応する |
| (15, 15) | margin | 白 rgb(255, 255, 255) |
反応しない |
要素の箱は左上 (30, 30) から 140 × 80(content 100 × 40 + padding 上下左右 20)でした。padding は要素の一部で、margin は要素の外であることが、色とクリックの両方から確かめられます。ボタンやリンクの押しやすさを上げたいときは、margin ではなく padding を広げます。
負の値とautoは marginだけ
getComputedStyle() で、指定がどう解釈されたかを確かめました(幅 200px の div、表示領域の幅 800px)。
| 指定 | 受け付けられたか | 算出値(上 右 下 左) |
|---|---|---|
margin: -10px |
受け付けられる | -10px -10px -10px -10px |
padding: -10px |
無効(指定が捨てられる) | 0px 0px 0px 0px |
margin: auto |
受け付けられる | 0px 300px 0px 300px(左右に余りを等分、上下は 0) |
padding: auto |
無効 | 0px 0px 0px 0px |
margin: auto の算出値から、通常の流れでは左右の auto だけが余りを分け合い、上下の auto は 0 になることも読み取れます。
marginとpaddingの書き方(1〜4値と論理プロパティ)
1〜4値の一括指定
margin と padding は、値の個数で適用される辺が決まります。書き方は両方とも同じです。
| 書き方 | 意味 | 算出値(上 右 下 左) |
|---|---|---|
margin: 10px |
4辺すべて | 10px 10px 10px 10px |
margin: 10px 20px |
上下 / 左右 | 10px 20px 10px 20px |
margin: 10px 20px 30px |
上 / 左右 / 下 | 10px 20px 30px 20px |
margin: 10px 20px 30px 40px |
上 / 右 / 下 / 左(時計回り) | 10px 20px 30px 40px |
padding: 1em 5% |
上下 1em / 左右 5%(親の幅 800px のとき) | 16px 40px 16px 40px |
個別に指定するときは margin-top・margin-right・margin-bottom・margin-left(padding も同様)を使います。
論理プロパティ(margin-inline / margin-block)
top・left のような物理的な方向の代わりに、文章の流れに沿った方向で指定する書き方です。横書きの日本語・英語では、inline が左右、block が上下にあたります。
| 論理プロパティ | 横書きでの意味 | 例と算出値(上 右 下 左) |
|---|---|---|
margin-inline |
左右 | margin-inline: 10px 30px → 0px 30px 0px 10px |
margin-block |
上下 | margin-block: 5px → 5px 0px 5px 0px |
padding-inline |
左右の padding | padding-inline: 1rem → 0px 16px 0px 16px |
margin-inline-start |
行の始まり側(横書きの左から右では左) | 下の表を参照 |
margin-block-start |
ブロックの始まり側(横書きでは上) | 下の表を参照 |
margin-inline-start: 30px と margin-block-start: 10px が、書字方向でどの辺になるかを測りました。
| 書字方向 | margin-inline-start: 30px が付く辺 |
margin-block-start: 10px が付く辺 |
|---|---|---|
| 横書き・左から右(既定) | 左 | 上 |
dir="rtl"(右から左) |
右(算出値 0px 30px 0px 0px) |
上 |
writing-mode: vertical-rl(縦書き) |
上 | 右(算出値 30px 10px 0px 0px) |
「左右だけ」「上下だけ」を1行で書けるのが、横書きだけのサイトでも便利な点です。 たとえば中央寄せは margin-inline: auto と書くと、上下の margin に触れずに済みます(幅 200px の箱が 400px の親の中で左から 100px の位置に来ることを実測で確認しました)。
ブラウザの既定の余白
何も指定しなくても、ブラウザの既定のスタイルで余白が付いている要素があります(Chromium 141、文字 16px のとき)。
| 要素 | 既定の margin(上 右 下 左) | 既定の padding |
|---|---|---|
body |
8px 8px 8px 8px |
0 |
h1 |
21.44px 0px 21.44px 0px |
0 |
p |
16px 0px 16px 0px |
0 |
ul |
16px 0px 16px 0px |
左に 40px |
「指定していないのに余白がある」ときは、開発者ツールの Computed(計算済み)タブで、どのスタイルが効いているかを確認できます。
marginの相殺が起きる3パターン(実測)
相殺(margin collapsing)とは、上下に隣り合うブロックの margin が足し算されず、1つにまとまる仕組みです。段落を続けて書いたときに間隔が倍にならないよう、CSS の仕様として用意されています。起きるのは上下方向だけで、左右では起きません。
以下の実測では、すべて高さ 50px の青い箱(.b)を使い、body の margin は 0 にしています。
body { margin: 0; }
.b { height: 50px; background: #9cf; }
パターン1:兄弟要素の間
上の要素の margin-bottom と、下の要素の margin-top が相殺します。
<div class="b" style="margin-bottom: 30px"></div>
<div class="b" style="margin-top: 20px"></div>
上の margin-bottom |
下の margin-top |
下の箱の上端 | 実際の間隔 | ルール |
|---|---|---|---|---|
| 30px | 20px | 80px | 30px(50 ではない) | 大きいほうが残る |
| 30px | 30px | 80px | 30px | 同じなら1つ分 |
| 30px | -10px | 70px | 20px | 正と負は足し算(30 + (-10)) |
| -30px | -10px | 20px | -30px(30px 重なる) | 負同士は絶対値の大きいほう |
パターン2:親と最初の子(最後の子)
親に padding も border もないとき、最初の子の margin-top は親の外に出て、親ごと下に押し下げます。 「子に margin-top を付けたら、親の上に余白ができた」という現象の正体です。
<div class="b"></div> <!-- 上の箱(0〜50px) -->
<div id="parent" style="background: #fc9">
<div id="child" class="b" style="margin-top: 40px"></div>
</div>
<div class="b"></div> <!-- 後ろの箱 -->
| 親の指定 | 親の上端 | 親の高さ | 子の上端 | 何が起きたか |
|---|---|---|---|---|
| 指定なし | 90px | 50px | 90px | 子の 40px が親の外に出た。親の背景は子と同じ高さしかない |
margin-top: 10px(子は 40px) |
90px | 50px | 90px | 親の 10px と子の 40px が相殺し、40px だけ残る |
padding-top: 1px |
50px | 91px | 91px | 相殺しない。親の内側に 40px の余白 |
border-top: 1px solid |
50px | 91px | 91px | 相殺しない |
display: flow-root |
50px | 90px | 90px | 相殺しない。寸法も増えない |
overflow: hidden |
50px | 90px | 90px | 相殺しない(はみ出しは切り取られる) |
display: flex(縦方向) |
50px | 90px | 90px | 相殺しない |
display: grid |
50px | 90px | 90px | 相殺しない |
最後の子の margin-bottom でも同じことが起きます。子に margin-bottom: 40px を付けた場合、親の高さは 50px のままで、40px の余白は親の外(後ろの箱との間)に出ていました。親に height: 80px を指定した場合は外に出なくなり、後ろの箱は親の直後(130px)に来ました。
パターン3:空の要素
高さも padding も border も中身もない要素は、自分の margin-top と margin-bottom 同士が相殺します。
<div class="b"></div>
<div style="margin-top: 20px; margin-bottom: 30px"></div> <!-- 空の要素 -->
<div class="b"></div>
| 空要素の指定 | 後ろの箱の上端 | 前後の箱の間隔 |
|---|---|---|
margin-top: 20px; margin-bottom: 30px |
80px | 30px(50 ではない) |
上に加えて、前の箱に margin-bottom: 10px、後ろの箱に margin-top: 10px |
80px | 30px(4つの margin がまとめて相殺) |
上に加えて、空要素に height: 1px |
101px | 51px(20 + 1 + 30。相殺しない) |
上に加えて、空要素に padding-top: 1px |
101px | 51px(相殺しない) |
スペーサー用の空の div に上下の margin を付けて「思ったより間隔が狭い」ときは、この相殺が原因です。
相殺のルールまとめ
| 組み合わせ | 残る値 |
|---|---|
| 正の値同士 | 大きいほう |
| 負の値同士 | 絶対値が大きいほう(より負のほう) |
| 正と負 | 足し算した値 |
| 3つ以上が隣り合う | 正の最大値と負の最小値を足した値 |
相殺しない条件一覧
相殺は「通常の流れの中で、上下に直接触れ合っているブロックの margin」だけで起きます。次の場合は起きません。兄弟の margin-bottom: 30px と margin-top: 20px で測った結果を添えます。
| 条件 | 間隔の実測 | 説明 |
|---|---|---|
| 通常のブロック同士(比較用) | 30px | 相殺する |
親が display: flex の子同士 |
50px | フレックスアイテムの margin は相殺しない |
親が display: grid の子同士 |
50px | グリッドアイテムの margin も相殺しない |
float した要素 |
50px | float した要素は相殺しない |
position: absolute の要素 |
- | 通常の流れから外れるため、親とも相殺しない(子の margin-top: 40px は親の内側で効き、親の位置は動かなかった) |
親に padding か border がある |
- | 親と子の margin が直接触れないので、親子の相殺が起きない |
親が display: flow-root・overflow: hidden など |
- | 親が独立した整形の範囲を作り、親子の相殺が起きない |
| 左右の margin | 50px | 横方向は常に足し算(inline-block 同士の margin-right: 30px と margin-left: 20px で確認) |
Flexbox や Grid でレイアウトを組んでいると相殺に出会いにくいのは、子同士も親子も相殺しないためです。 反対に、同じコンポーネントを通常のブロックの中に移すと間隔が変わることがあるので、間隔の取り方をあらかじめ決めておくと安定します(後述の「gap との使い分け」)。
marginやpaddingが効かない原因チェック表
「指定したのに余白が変わらない」ときは、次の表を上から順に確認してください。
| 症状 | 原因 | 解決策 |
|---|---|---|
span や a の上下の margin が効かない |
インライン要素には上下の margin が効かない | display: inline-block か block にする |
span の上下の padding が前後の行に重なる |
インライン要素の上下 padding は行の高さに反映されない | display: inline-block にする |
| 上下の間隔が足し算にならない | 兄弟の相殺 | 片方だけに margin を付ける、または親を flex にして gap を使う |
子の margin-top で親ごと下がる。親の背景が広がらない |
親子の相殺 | 親に display: flow-root、または子の margin を親の padding に置き換える |
margin: 0 auto で中央に寄らない |
幅が未指定、またはインライン系の要素 | display: block と幅(width / max-width)を指定する |
margin: auto で上下中央にならない |
通常の流れでは上下の auto は 0 | 親を display: flex か grid にする |
margin-top: 10% が思った大きさにならない |
% は親の幅が基準 |
px・rem、または vh など目的に合う単位を使う |
| padding を付けたら幅がはみ出す | box-sizing: content-box(既定)では padding が幅の外に足される |
box-sizing: border-box を指定する |
height: 50% が効かず、下の余白も出ない |
親の高さが未指定(auto)だと % の高さは計算できない |
親に高さを指定する、または min-height や flex / grid で組む |
| 開発者ツールで取り消し線が付いている | 別のセレクタの指定が優先されている、または値が無効 | 詳細度と記述順を確認する。padding: -10px などは無効 |
主な項目を、実測の数値で確かめていきます。
インライン要素の上下margin・padding
幅 400px の親の中で、文字の間に置いた span を測りました(行の高さ 24px)。
span の指定 |
span の左端 |
span の上端 |
span の箱 |
親の高さ |
|---|---|---|---|---|
| 指定なし | 16px | 3px | 32 × 17 | 24px |
margin: 30px |
46px(左右は効く) | 3px(上下は効かない) | 32 × 17 | 24px |
padding: 20px |
16px | -17px(上にはみ出す) | 72 × 57 | 24px(行の高さは変わらない) |
display: inline-block; margin: 30px |
46px | 30px | 32 × 24 | 84px(24 + 上下 60) |
インライン要素は、左右の margin / padding は効き、上下は「行の高さ」に反映されません。 display: inline-block にすると上下も効くようになります。display の値ごとの違いは、当サイトの「CSS displayの種類一覧」の記事で詳しく比べています。
margin: auto が効く条件
幅 400px(一部は高さ 300px)の親の中で、幅 200px・高さ 50px の箱の位置を測りました。
| 条件 | 箱の左端 | 箱の上端 | 結果 |
|---|---|---|---|
display: block + width: 200px + margin: 0 auto |
100px | 0 | 左右中央に寄る |
display: block、幅の指定なし + margin: 0 auto |
0(幅 400px) | 0 | 親いっぱいに広がるので、余りがない |
display: inline-block + width: 200px + margin: 0 auto |
0 | 0 | 寄らない(auto は 0 扱い) |
display: block + margin: auto(親の高さ 300px) |
100px | 0 | 左右だけ中央。上下は 0 |
親が display: flex + margin: auto |
100px | 125px | 上下左右とも中央 |
position: absolute; inset: 0 + margin: auto |
100px | 125px | 上下左右とも中央 |
親が flex、子に margin-left: auto |
350px | 0 | 右端に寄る(余りをすべて左に割り当てる) |
margin: auto は「余っている幅(高さ)を自動で割り当てる」指定なので、余りがあることが条件です。inline-block を中央に置くときは、親に text-align: center を指定します。中央寄せの全パターンは、当サイトの「CSS 中央寄せの方法」の記事にまとめています。
% は親の「幅」が基準
幅 400px・高さ 200px の親の中で測りました。
| 指定 | 実測 | 計算 |
|---|---|---|
margin-top: 10% |
上に 40px | 親の幅 400px × 10%(高さ 200px の 10% = 20px ではない) |
margin-left: 10% |
左に 40px | 親の幅 400px × 10% |
padding: 10%(中身なし) |
箱の高さ 80px | 上下とも 40px(親の幅が基準) |
上下方向でも幅が基準になるのは仕様どおりの動きです。この性質は、以前は「縦横比を保つ箱」を作るために使われていました。現在は aspect-ratio プロパティで直接書けます。
box-sizing で幅の数え方が変わる
width: 200px; height: 100px; padding: 20px; border: 5px solid を指定した箱の、実際の大きさです。
box-sizing |
実際の箱 | 計算 |
|---|---|---|
content-box(既定) |
250 × 150 | 幅 200 + padding 40 + border 10 |
border-box |
200 × 100 | padding と border を含めて 200 × 100 |
幅 400px の親の中で width: 100% と組み合わせると、差がはっきり出ます。
| 子の指定 | 子の幅 | 結果 |
|---|---|---|
width: 100%; padding: 20px |
440px | 親から 40px はみ出す |
box-sizing: border-box; width: 100%; padding: 20px |
400px | 親に収まる |
width: 100%; margin: 0 20px |
400px(左端 20px) | 右に 20px はみ出す |
幅の指定なし + margin: 0 20px |
360px | 親に収まる(ブロックは margin の分だけ自動で縮む) |
多くのサイトでは、次の指定を最初に入れて、すべての要素を border-box に揃えています。
*, *::before, *::after { box-sizing: border-box; }
margin は box-sizing に関係なく、常に幅の外側です。 width: 100% の要素に左右の margin を付けるとはみ出すため、幅の指定を外すか、親の padding で余白を作ります。
高さが未指定だと % の高さは 0 になる
| 親 | 子の height: 50% |
結果 |
|---|---|---|
| 高さの指定なし(auto) | 0px | 基準がないため計算できない |
height: 200px |
100px | 親の高さの 50% |
スクロールする箱(overflow: auto)の中の最後の子に margin-bottom: 50px を付けたケースも測りました。高さ 100px の親の中に高さ 100px の子を入れると、scrollHeight は 150 になり、Chromium 141 では下の margin もスクロール範囲に含まれていました。
解決策3つ(flow-root・gap・padding置換)
解決策1:親に display: flow-root(親子の相殺を止める)
/* 直す前:子の margin-top が親の外に出る */
.card { background: #fc9; }
.card > h2 { margin-top: 40px; }
/* 直した後:親が margin を内側に閉じ込める */
.card { background: #fc9; display: flow-root; }
実測では、親の上端が 90px から 50px に戻り、親の高さが 50px から 90px(子の margin 40px を含む)になりました。padding-top: 1px や border-top でも止まりますが、寸法が 1px 増えます。flow-root は寸法を変えません。 また flow-root は、float した子を親の高さに含める効果もあります(高さ 0 だった親が 50px になることを確認)。
解決策2:親で間隔を管理する(flex / grid + gap)
/* 直す前:子それぞれに margin。相殺や、端の余白の調整が必要 */
.list > .item { margin-bottom: 20px; }
/* 直した後:親が間隔を決める。相殺は起きない */
.list { display: flex; flex-direction: column; gap: 20px; }
gap: 20px の縦並びでは、2つ目の箱の上端が 70px(50 + 20)でした。gap は「要素と要素の間」だけに入り、最初と最後の外側には付きません。
解決策3:marginをpaddingに置き換える
/* 直す前:子の margin で親の内側に余白を作ろうとしている */
.box > :first-child { margin-top: 40px; }
/* 直した後:親の padding で内側の余白を作る */
.box { padding-top: 40px; }
「親の内側の余白」は、もともと padding の役割です。親の中の余白は親の padding、兄弟同士の間隔は gap か margin、と役割を分けると、相殺を意識する場面が減ります。
通常のブロックで間隔をそろえる書き方
flex にしない場合は、「2つ目以降の要素の上にだけ margin を付ける」書き方が便利です。
.stack > * + * { margin-top: 16px; }
高さ 50px の箱を3つ並べると、上端は 0・66・132px、親の高さは 182px(最後の下に余白なし)でした。margin の向きを上だけに統一しているので、兄弟の相殺も起きません。
コピペ用:余白の基本セットと確認の手順
ここまでの内容を、そのまま貼って使える形にまとめます。最初に入れておくと、「はみ出す」「親ごと下がる」「間隔が倍にならない」といった場面が減ります。
/* 1. 幅の数え方を border-box に揃える(padding を付けても幅が変わらない) */
*, *::before, *::after { box-sizing: border-box; }
/* 2. body の既定の margin(8px)をなくす */
body { margin: 0; }
/* 3. 内側の余白は親の padding で作る */
.card { padding: 24px; display: flow-root; }
/* 4. 等間隔に並べるときは親の gap */
.row { display: flex; flex-wrap: wrap; gap: 16px; }
.stack { display: flex; flex-direction: column; gap: 16px; }
/* 5. 箱を左右中央に置く(幅の指定とセット) */
.container { max-width: 960px; margin-inline: auto; padding-inline: 16px; }
/* 6. 押しやすいリンク(上下の余白を効かせるために inline-block) */
.button { display: inline-block; padding: 12px 20px; }
それでも意図と違う余白になったときは、ブラウザの開発者ツールで次の順に確認すると、原因を絞り込めます。
| 手順 | 見る場所 | 分かること |
|---|---|---|
| 1 | 要素を選び、Computed(計算済み)タブのボックスモデルの図を見る | margin・border・padding・content の実際の px。相殺していても、ここには指定した値が表示される |
| 2 | ページ上で要素にカーソルを合わせる | margin と padding が色分けして重ねて表示される。親の外にはみ出た margin が見える |
| 3 | Styles(スタイル)タブで取り消し線を探す | 別の指定に上書きされた宣言、または無効な値(padding: -10px など) |
| 4 | display の算出値を確認する |
inline なら上下の margin は効かない。親が flex / grid なら相殺は起きない |
| 5 | 親の要素でも 1〜4 を繰り返す | 親子の相殺、親の padding、親の高さが未指定かどうか |
gapとmarginの使い分け
gap は、Flexbox・Grid(および段組み)の親に指定して、子と子の間隔を決めるプロパティです。幅 320px の折り返すフレックスコンテナに、幅 100px の箱を5つ入れて比べました。
/* A: gap */
.wrap { display: flex; flex-wrap: wrap; width: 320px; gap: 10px; }
/* B: margin */
.wrap { display: flex; flex-wrap: wrap; width: 320px; }
.wrap > .item { margin-right: 10px; margin-bottom: 10px; }
| 方法 | 1行に並んだ数 | 親の高さ | 理由 |
|---|---|---|---|
A: gap: 10px |
3つ(左端 0・110・220) | 110px | 間は2か所だけ。100 × 3 + 10 × 2 = 320 でぴったり収まる |
B: margin-right: 10px ほか |
2つ | 180px | 3つ目の右にも 10px が付き、110 × 3 = 330 で収まらない。最後の行の下にも 10px 余る |
| 比べる点 | gap |
margin |
|---|---|---|
| 指定する場所 | 親 | 子 |
| 端の余白 | 付かない | 付く(最後の要素の分を打ち消す工夫が必要) |
| 相殺 | 起きない | 通常のブロックでは起きる |
| 使える場所 | flex・grid・段組みの親 | どの要素でも |
| 負の値 | 指定できない(無効) | 指定できる |
| 1つだけ間隔を変える | 不向き | 向いている |
auto で寄せる |
できない | できる(margin-left: auto など) |
使い分けの目安は次のとおりです。
| 場面 | 向いている指定 |
|---|---|
| 同じ種類の要素を等間隔に並べる(カード、ボタン、メニュー) | 親に gap |
| セクションとセクションの間、見出しの上など、個別の間隔 | margin(向きは上か下のどちらかに統一) |
| 枠と中身の間、ボタンの押せる範囲 | padding |
| 1つだけ右端に寄せる | margin-left: auto(親が flex のとき) |
| 箱を左右中央に置く | margin-inline: auto + 幅の指定 |
Flexbox と Grid のどちらで並べるかは、当サイトの「FlexboxとGridの使い分け」の記事で比較しています。
よくある質問
Q. margin と padding のどちらを使うか迷ったときの決め方は? A. 3つの質問で決められます。(1) 背景色や枠線の内側に余白がほしい → padding。(2) クリックやタップに反応する範囲を広げたい → padding。(3) ほかの要素との間隔を空けたい → margin(親が flex / grid なら gap)。実測のとおり、padding は背景が塗られてクリックにも反応し、margin はどちらも対象外です。
Q. 相殺は左右の margin でも起きますか?
A. 起きません。相殺は上下(ブロック方向)の margin だけの仕組みです。margin-right: 30px と margin-left: 20px の inline-block を並べた実測では、間隔は足し算の 50px でした。また、flex や grid の子同士では上下でも相殺せず、30px と 20px の間隔は 50px になりました。
Q. 相殺を意図的に利用する場面はありますか?
A. 文章の段落がその例です。p には上下に 16px ずつの margin が既定で付いていますが、相殺のおかげで段落の間隔は 32px ではなく 16px になり、見出しやリストが混ざっても間隔が倍になりません。記事の本文のように「ブロックが縦に続く文章」では相殺が自然に働くので、そのまま活かすのが扱いやすい方法です。
Q. 負の margin はどんなときに使いますか?
A. 親の padding を打ち消して画像だけを端まで広げる(margin-inline: -16px)、要素を少し重ねる、といった用途です。margin: -10px は算出値でも -10px として有効でした。レイアウト全体を負の margin で組むと追いかけにくくなるので、部分的な調整にとどめると読みやすい CSS になります。
まとめ
- margin は border の外側、padding は内側。 背景色が塗られ、クリックに反応するのは padding まで(実測で padding は青・反応あり、margin は白・反応なし)。
- 負の値と
autoを指定できるのは margin だけ。padding: -10pxやpadding: autoは無効になる。 - 相殺は上下の margin だけで起き、兄弟・親子・空要素の3パターンがある。 30px と 20px が並ぶと間隔は 30px。
- flex / grid の子、
flow-rootの親、padding や border のある親では相殺しない。 同じ指定で間隔は 50px になった。 - 効かないときは「インライン要素の上下」「相殺」「auto の条件」「% は親の幅基準」「box-sizing」「高さ未指定」を順に確認する。
- 解決策は、親に
display: flow-root、親でgap、内側の余白はpaddingに置き換える、の3つ。 - 等間隔に並べるなら gap、個別の間隔や寄せは margin、枠と中身の間は padding と役割を分ける。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS marginとpaddingの違い|相殺と効かない原因一覧」
株式会社RJCでは、marginとpaddingをはじめとするCSSレイアウトの基礎を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。