一张图看懂区别
padding 在边框以内,margin 在边框以外。 下面两个盒子的内容相同,数值都是 24px,只有属性不同。灰色是它们后面的容器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Margin vs padding</title>
<style>
body { font-family: system-ui, sans-serif; }
.row { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.container { display: flow-root; background: #e5e7eb; width: max-content; }
.box {
border: 3px solid #111827;
background: #2563eb;
color: white;
}
.with-padding { padding: 24px; }
.with-margin { margin: 24px; }
.label { font-size: 13px; margin: 6px 0 0; color: #111827; }
</style>
</head>
<body>
<div class="row">
<div>
<div class="container"><div class="box with-padding">Text</div></div>
<p class="label">padding: 24px</p>
</div>
<div>
<div class="container"><div class="box with-margin">Text</div></div>
<p class="label">margin: 24px</p>
</div>
</div>
</body>
</html>
用 padding 时,这 24px 是蓝色的:它是盒子的一部分,位于边框内部,盒子会变大。用 margin 时,这 24px 是灰色的:盒子紧贴着文字,外面的空间把容器的边缘推开。
在同一个盒子上试试两者
拖动两个滑块。padding 让蓝色盒子变大;margin 让盒子离开灰色边缘,但盒子本身不变。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sliders</title>
<style>
body { font-family: system-ui, sans-serif; }
label { display: block; margin-bottom: 6px; }
.container { display: flow-root; background: #e5e7eb; width: max-content; margin-top: 10px; }
#box { border: 3px solid #111827; background: #2563eb; color: white; }
</style>
</head>
<body>
<label>padding <input id="p" type="range" min="0" max="40" value="10"> <span id="pv"></span></label>
<label>margin <input id="m" type="range" min="0" max="40" value="10"> <span id="mv"></span></label>
<div class="container"><div id="box">Box</div></div>
<p id="size"></p>
<script>
const box = document.getElementById('box');
const p = document.getElementById('p');
const m = document.getElementById('m');
const update = () => {
box.style.padding = p.value + 'px';
box.style.margin = m.value + 'px';
document.getElementById('pv').textContent = p.value + 'px';
document.getElementById('mv').textContent = m.value + 'px';
const r = box.getBoundingClientRect();
document.getElementById('size').textContent =
'Blue box: ' + Math.round(r.width) + ' x ' + Math.round(r.height) + 'px';
};
p.addEventListener('input', update);
m.addEventListener('input', update);
update();
</script>
</body>
</html>
留意显示尺寸的那一行:拖动 padding 滑块时它会变化,拖动 margin 滑块时它保持不变。
margin 与 padding 一览
| padding(内边距) | margin(外边距) |
|---|
| 位置 | 边框以内 | 边框以外 |
| 背景 | 显示元素的背景 | 始终透明 |
| 属于点击区域 | 是 | 否 |
| 增大元素尺寸 | 是,在 content-box 下 | 否 |
可以取 auto | 否 | 可以(margin: 0 auto 用来居中) |
| 可以取负值 | 否 | 可以 |
| 垂直方向会合并 | 从不 | 会,相邻的垂直外边距会合并 |
| 百分比相对于 | 包含块的宽度 | 包含块的宽度 |
| 典型用途 | 按钮、卡片、输入框内部的空间 | 元素之间的空间、居中 |
每个属性都有单独的一页介绍所有细节:CSS padding 和 CSS margin。
该用哪一个
问自己一个问题:这段空间是属于元素本身,还是位于元素之间?
- 按钮文字周围的空隙、卡片的内部、输入框文字与边框之间的距离:用 padding。它会带上背景,并让可点击的目标变大。
- 两个段落之间、卡片之间、一个区块周围的空间:用 margin,或者当父元素是 flex 或 grid 容器时用
gap。
点击区域是最需要做出正确选择的地方。下面两个链接在页面上占用的空间相同,但第一个的空间来自 padding,第二个的空间来自 margin。只有第一个容易点中:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Click area</title>
<style>
a {
display: inline-block;
background: #2563eb;
color: white;
text-decoration: none;
outline: 2px dashed #f59e0b; /* the clickable area */
}
.pad { padding: 14px 24px; }
.mar { margin: 14px 24px; }
</style>
</head>
<body>
<a class="pad" href="#">Padding: big target</a>
<a class="mar" href="#">Margin: tiny target</a>
</body>
</html>
琥珀色虚线轮廓就是元素的边缘,也就是响应点击和触摸的区域。第二个链接周围的外边距只是什么都不做的空白。
元素之间的间距:margin 还是 gap
对于一行或一组网格中的元素,在 flex 或 grid 父元素上使用 gap,通常比给每个子元素加外边距更干净:它只出现在元素之间,从不出现在第一个元素之前或最后一个元素之后,所以不需要再做任何抵消。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>gap</title>
<style>
.list { display: flex; gap: 12px; background: #e5e7eb; padding: 12px; }
.item { background: #16a34a; color: white; padding: 12px 16px; }
</style>
</head>
<body>
<div class="list">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three</div>
</div>
</body>
</html>
这里灰色容器使用 padding(容器内部的空间,灰色),各个元素使用 padding(每个元素内部的空间,绿色),而 gap 负责它们之间的空间。
常见错误
- 用 margin 做需要上色的空间。 margin 是透明的。如果这段空间需要显示背景,那就是 padding。
- 用 margin 让链接变大。 点击区域到边框为止;请用 padding。
- 以为两个 20px 的垂直外边距会得到 40px。 相邻的垂直外边距会合并成 20px。padding 永远不会合并。
- 尝试用
padding: auto 居中。 只有 margin 接受 auto。
- 忘了 padding 会让盒子变大。 加上
box-sizing: border-box,让 width 把它包含在内。