CSS 如何实现水平垂直居中?
简化版
水平垂直居中最常用 Flex 或 Grid。Flex 写 display: flex; justify-content: center; align-items: center;,Grid 写 display: grid; place-items: center;。绝对定位加 transform 也常见。
详细版
常见方案:
.parent {
display: flex;
justify-content: center;
align-items: center;
}
Flex 适合容器内单个或多个元素整体居中。
.parent {
display: grid;
place-items: center;
}
Grid 写法更短,适合单元素居中。
绝对定位方案:
.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
它不要求知道子元素宽高,但父元素需要有定位上下文。面试时最好按场景说:现代布局优先 Flex/Grid,兼容老代码可用定位或 margin auto。
完整版教学
一、居中要先区分对象和方向
面试问居中,不要急着背代码。先分清楚:是文本居中、块元素居中、已知宽高元素居中,还是未知宽高元素居中;是水平、垂直,还是两者都要。
文本水平居中:
.text {
text-align: center;
}
块元素水平居中:
.box {
width: 300px;
margin: 0 auto;
}
这种方案要求块元素有明确宽度。
二、Flex 是最常用答案
Flex 的好处是语义直接、适应内容大小、兼容性好。
.parent {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
justify-content 沿主轴居中,默认主轴水平;align-items 沿交叉轴居中,默认交叉轴垂直。
三、Grid 的 place-items 更简洁
Grid 的 place-items 是 align-items 和 justify-items 的简写:
.parent {
display: grid;
place-items: center;
}
如果只是让一个卡片在容器中居中,这个写法非常清爽。
四、定位方案为什么还要会
定位加 transform 常用于弹窗、浮层、loading 等脱离文档流的元素。
.modal {
position: fixed;
inset: 50% auto auto 50%;
transform: translate(-50%, -50%);
}
left: 50%; top: 50% 移动的是元素左上角,translate(-50%, -50%) 再按自身宽高反向移动一半,所以能适配未知宽高。
五、面试追问与工程落地
居中题常被追问“未知宽高怎么做”。Flex/Grid 和绝对定位加 transform 都不需要提前知道子元素尺寸;而 margin: auto 水平居中通常要求块元素有宽度,传统绝对定位负 margin 则要求已知宽高。
垂直居中还要看父容器有没有高度。很多代码写了 align-items: center 却没效果,是因为父容器高度只被内容撑开,没有额外空间可供居中。面试时补一句“容器需要有可分配空间”,能避免显得只会背代码。
工程里还要考虑多行文本、图片加载、移动端安全区。比如弹窗居中时,纯 top: 50% 可能在小屏键盘弹出后体验不好;更稳的做法是结合 max-height、overflow、padding 和响应式断点,让内容超出时可滚动。
六、用剩余空间解释居中是否生效
假设父容器高 500px,子元素高 140px,Flex 交叉轴有 500 - 140 = 360px 的剩余空间,align-items: center 会把它分到上下两侧,各 180px。如果父容器高度也是由这个 140px 子元素撑开的,剩余空间为 0px,声明没有可分配空间,视觉上自然看不出垂直移动。
| 场景 | 推荐写法 | 必要条件或代价 |
|---|---|---|
| 文本水平居中 | text-align: center | 控制行内内容,不负责块盒自身 |
| 单个未知尺寸组件 | Grid place-items: center | 容器要有额外空间 |
| 多项目整体居中 | Flex 两轴对齐 | 注意主轴会随 flex-direction 改变 |
| 浮层相对视口居中 | fixed + inset / transform | 脱离文档流,需处理溢出和键盘 |
| 固定宽块水平居中 | margin-inline: auto | inline 方向必须存在可分配空间 |
居中失效时先问“谁在什么轴上、相对哪个对齐容器、还有多少剩余空间”,这比继续叠加属性更容易定位根因。
七、常见误区与追问
- 误区:
justify-content永远控制水平方向。 它控制 Flex 主轴;当flex-direction: column时,主轴是垂直方向。 - 误区:写了
align-items: center就一定能看到垂直居中。 容器若没有确定或可用的额外高度,交叉轴没有剩余空间可分配。 - 误区:
place-items: center在 Flex 和 Grid 中含义完全一样。 Grid 同时支持两个自对齐轴;Flex 中justify-items不参与 flex item 的主轴排列,通常应明确使用justify-content与align-items。 - 追问:未知宽高元素为什么可以用 transform 居中? 百分比 inset 按包含块计算,而
translate的百分比按元素自身参考盒计算,反向移动一半即可修正左上角落点。 - 追问:绝对定位后四边设为零再用
margin: auto能居中吗? 在具有可解析尺寸且四个 inset 提供可用空间时可以;未知尺寸和不同轴的收缩规则需要结合实际盒计算。 - 追问:多行内容超出视口时还应强制几何中心吗? 不一定,弹窗通常要设置最大高度、可滚动内容区和安全边距,避免顶部内容被裁掉且无法访问。
- 追问:
vertical-align: middle为什么不能让普通块在父盒里垂直居中? 它主要影响行内级盒或表格单元格在相应格式化上下文中的对齐,不是普通块布局的通用垂直居中属性。
八、加强记忆
居中题别只背一种写法。普通组件居中优先 Flex,单元素容器居中可以 Grid,浮层居中用定位加 transform,文本水平居中用 text-align,固定宽块水平居中用 margin: auto。