margin 是什么
margin(外边距)是元素边框外侧的空间。它始终是透明的,作用是把其他元素推开。在下面的示例中,灰色容器透过蓝色盒子周围的外边距显露出来:
灰色的那一圈不属于盒子:盒子自身的背景到边框就停止了。如果想要带有元素背景的空间,请使用 padding。
margin 简写
margin 接受一到四个值,顺序和 padding 一样,按顺时针排列:
| 声明 | 上 | 右 | 下 | 左 |
|---|---|---|---|---|
margin: 10px; | 10 | 10 | 10 | 10 |
margin: 10px 20px; | 10 | 20 | 10 | 20 |
margin: 10px 20px 30px; | 10 | 20 | 30 | 20 |
margin: 10px 20px 30px 40px; | 10 | 20 | 30 | 40 |
每一边也有自己的属性(margin-top、margin-right、margin-bottom、margin-left),还有跟随文字方向的逻辑属性(margin-inline-start、margin-inline-end、margin-block、margin-inline)。
和 padding 不同,margin 可以取 auto 和负值:
| 值 | 示例 | 说明 |
|---|---|---|
| 长度 | 16px、1.5rem | 最常用 |
| 百分比 | 5% | 四条边都相对于包含块的宽度计算 |
auto | margin: 0 auto | 由浏览器填入剩余空间 |
| 负值 | margin-top: -10px | 把元素或相邻元素拉近,可能重叠 |
用 margin: 0 auto 居中
margin: 0 auto 是让块级元素水平居中的经典写法。两侧都设为 auto,就是告诉浏览器把剩余空间平均分配。元素的宽度必须小于容器,否则没有剩余空间可分:
在常规流中,auto 外边距不能垂直居中(垂直方向的 auto 外边距会变成 0),对行内元素也不起作用。想全面了解居中方法,请看如何让 div 居中。
外边距折叠
两个垂直外边距相接时,它们不会相加,浏览器只保留较大的那个。这里第一个盒子设置了 margin-bottom: 30px,第二个设置了 margin-top: 20px,它们之间的间距是 30px,而不是 50px:
折叠是有意设计的:它让段落和标题可以各自带上自己的间距,相遇时又不会翻倍。真正容易让人踩坑的是第二种情况:子元素的上外边距跑出了父元素:
在第一个父元素中,子元素 30px 的外边距穿过父元素的上边缘发生了折叠,所以它把整个父元素往下推,而不是在父元素内部留出灰色空间。下面任意一种做法都能阻止它:
- 给父元素设置
display: flow-root(和overflow: hidden不同,它不会裁剪任何内容)。 - 给父元素的上边缘加上内边距或边框。
- 让父元素成为 flex 或 grid 容器:flex 和 grid 项目的外边距永远不会折叠。
水平外边距永远不会折叠,浮动元素和绝对定位元素的外边距也不会。
负外边距
负外边距朝相反方向拉。设在上方或起始一侧时,它移动的是元素本身;设在下方或结束一侧时,它把下一个元素拉近。盒子之间可能重叠:
flexbox 中的 margin auto
在 flex 容器中,auto 外边距会占据它那一侧的全部剩余空间。这是把某一项推到一行最末端的最简单方法,而且在 flexbox 中 auto 在垂直方向上同样有效:
margin-inline-start: auto 把剩余空间放在“Log in”之前,无论页面是从左到右还是从右到左,它都会出现在这一行的末端。
常见错误
- 在没有宽度的元素上使用
margin: 0 auto。 块级元素本来就会占满容器;请设置width或max-width。 - 在行内元素上使用
margin: auto。 保持行内的span、a或img的 auto 外边距等于 0。把它改成display: block。 - 把两个垂直外边距相加,以为会得到它们的和。 它们会折叠成较大的那个;在 flex 或 grid 中使用
gap,或者始终只用一个方向的外边距。 - 子元素的外边距把父元素推开。 这是父子外边距折叠;给父元素加上
display: flow-root。 - 在需要背景的地方用 margin 留空。 margin 是透明的;请改用 padding。
常见问题
CSS 中的 margin 是什么?
margin(外边距)是元素边框外侧的空间。它是透明的,会把相邻的元素推开。可以用 margin 设置,也可以用单边属性 margin-top、margin-right、margin-bottom 和 margin-left 分别设置。
margin: 0 auto 有什么作用?
它把上下外边距设为 0,再把水平方向剩余的空间平均分给左右外边距,于是块级元素在水平方向上居中。元素的宽度必须小于容器,例如 max-width: 600px。
为什么 margin auto 没有让元素居中?
通常是因为元素没有设置宽度(块级元素会占满容器,没有剩余空间可分),或者它是行内元素(默认的 span、a、img),行内元素的 auto 外边距等于 0。给它设置宽度和 display: block,或者在父元素上用 flexbox 或 grid 来居中。
什么是外边距折叠?
两个垂直外边距相遇时,例如一个段落的下外边距和下一个段落的上外边距,浏览器只取较大的那个,而不是把两者相加。这只发生在常规流中块级盒子的垂直外边距上,flex 和 grid 布局中不会发生。
margin 可以是负值吗?
可以。负外边距会把元素往那一侧拉,或者把下一个元素拉到它上面,因此盒子之间可能重叠。它适合做细微的对齐调整,也可以让元素突破容器的内边距。