"怎么让一个 div 居中"是前端面试出现频率最高的问题之一。但面试官真正想看的不是你背出几种写法,而是三件事:你知不知道每种方案的适用场景、有没有踩过坑、以及在真实项目里会选哪一个。
先看一个常见的翻车现场:很多人脱口而出 margin: 0 auto,结果元素在垂直方向纹丝不动。因为 margin: auto 只对块级元素的水平方向生效,垂直方向需要额外的条件(比如 flex 或绝对定位)。
这篇文章按"水平居中 → 垂直居中 → 水平垂直居中"的顺序,把常见方案一次讲清,每种都注明适用场景和坑点,最后给出选型建议。
一、水平居中
1. 行内元素:text-align
给父元素加 text-align: center,子元素是 inline / inline-block / inline-flex 时即可水平居中。
<div class="parent">
<span>我是行内元素</span>
</div>
.parent {
text-align: center;
}
注意它作用于行内内容,对块级子元素无效。
2. 块级定宽元素:margin auto
元素必须有明确宽度,且不能是 float 或绝对定位,margin: 0 auto 才会生效。
.box {
width: 300px;
margin: 0 auto;
}
这是最经典、兼容性最好的水平居中方式。
3. flex 布局
.parent {
display: flex;
justify-content: center;
}
不要求子元素定宽,是目前最推荐的方式。
二、垂直居中
4. 单行文本:line-height
让 line-height 等于容器高度,适用于单行文本。
.parent {
height: 60px;
line-height: 60px;
}
超过一行就会溢出,多行文本不适用。
5. flex 布局
.parent {
display: flex;
align-items: center;
}
同样不要求子元素高度,推荐。
三、水平垂直居中
6. flex + margin auto(推荐)
父元素开启 flex,子元素用 margin: auto 就能同时水平垂直居中,这是很多人不知道的技巧。
.parent {
display: flex;
}
.child {
margin: auto;
}
优点是不需要知道子元素尺寸,多余空间自动平分到四个方向。
7. grid 布局
.parent {
display: grid;
place-items: center;
}
place-items: center 是 align-items 和 justify-items 的简写,一行搞定,语法最简洁。
8. 绝对定位 + transform
需要父元素 position: relative,子元素绝对定位后用 transform 回拉自身一半。
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
这是 flex 普及前最主流的方案,不依赖子元素尺寸。translate 的百分比是相对元素自身计算的,这正是它能精确居中任意宽高元素的原因。
9. 绝对定位 + inset + margin auto
子元素有明确宽高时,还可以这样写:
.child {
position: absolute;
inset: 0;
width: 200px;
height: 100px;
margin: auto;
}
inset: 0 让四个方向的偏移都为 0,配合定宽高和 margin: auto,浏览器会把剩余空间平均分配,从而实现居中。缺点是必须知道元素尺寸。
四、怎么选?
| 场景 | 推荐方案 |
|---|---|
| 行内元素水平居中 | text-align: center |
| 定宽块级水平居中 | margin: 0 auto |
| 未知尺寸水平垂直居中 | flex + margin: auto 或 place-items: center |
| 需要脱离文档流的居中(如弹窗) | 绝对定位 + transform |
| 旧浏览器兼容 | 绝对定位 + transform(iOS 8+ / IE9+) |
一句话总结:能用 flex / grid 就用它们,简单、语义清晰、不依赖元素尺寸;只有在需要脱离文档流或兼容老浏览器时,才回到绝对定位 + transform 的写法。
五、几个容易踩的坑
margin: 0 auto对垂直方向不生效,别指望它上下居中。line-height居中只适合单行文本,多行会互相重叠。- 绝对定位居中时,父元素必须设置
position: relative(或非 static),否则会相对更外层甚至 viewport 定位。 transform: translate(-50%, -50%)可能触发模糊或影响子元素的position: fixed,弹窗场景要留意。display: flex之后子元素的float、clear、vertical-align会失效,别混用。
把这几种方案分场景记住,面试和实际开发都不会再卡在这道题上。