技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTCSS

CSS 实现水平垂直居中的方式

所属馆藏
CSS
文件格式
Markdown
原始路径
CSS/09-CSS实现水平垂直居中的方式
本文目录12 个章节
  1. 一、水平居中
  2. 二、单行文本的垂直居中
  3. 三、使用绝对定位居中
  4. 四、使用 Flexbox
  5. 五、使用 CSS Grid
  6. 六、使用 display: table-cell
  7. 七、使用 line-height 和 vertical-align 对图片居中
  8. 八、使用 padding 实现内容周围等距
  9. 九、各种方案的选择
  10. 十、常见排查问题
  11. 总结
  12. 参考资料

CSS 实现水平垂直居中的方式

Category(分类): CSS Status: 已整理

“如何让一个元素水平垂直居中?”看似简单,但实现方式取决于很多条件:

  • 子元素是块级元素、行内元素还是行内块元素?
  • 子元素尺寸是否确定?
  • 父元素是否有明确的宽高?
  • 是否需要兼容旧浏览器?
  • 需要水平居中、垂直居中,还是两个方向同时居中?

现代项目优先考虑 Flexbox 和 Grid。绝对定位、表格布局、line-height 和百分比 padding 仍然有特定适用场景,也值得了解。

一、水平居中

1. 块级元素使用 margin: 0 auto

margin: 0 auto 应该设置在需要居中的子元素上,而不是父元素上:

<div class="parent">
  <div class="child">块级元素</div>
</div>
.parent {
  width: 100%;
}

.child {
  width: 200px;
  margin: 0 auto;
}

使用条件:

  • 子元素应处于普通块布局中;
  • 子元素需要有明确宽度,或宽度受到 max-width 等约束;
  • 子元素不能宽于父元素,否则可能出现溢出。

如果子元素的 widthauto,块级元素通常会占满可用宽度,此时不会表现为一个有可见左右空白的“居中盒子”。

2. 行内元素和行内块元素使用 text-align: center

.parent {
  text-align: center;
}

.child {
  display: inline-block;
}

text-align 作用于父元素的行内内容,因此可以让文本、图片和行内块元素水平居中,但不能直接让普通块级子元素水平居中。

二、单行文本的垂直居中

使用相同的 heightline-height

.text {
  width: 200px;
  height: 200px;
  color: #333;
  text-align: center;
  line-height: 200px;
  background: skyblue;
}
<div class="text">单行文本垂直居中</div>

这种方法适合单行文本。对于多行文本,固定 line-height 会造成布局异常,应使用 Flex、Grid、表格单元格或其他适合多行内容的方案。

三、使用绝对定位居中

绝对定位方案需要先确认定位包含块。通常给父元素设置:

.parent {
  position: relative;
}

1. 已知尺寸:负外边距

如果子元素宽高已知,可以将子元素左上角移动到父元素中心,再通过负外边距移动回自身尺寸的一半:

<div id="box">
  <div id="child">已知尺寸</div>
</div>
#box {
  position: relative;
  width: 300px;
  height: 300px;
  background: #ddd;
}

#child {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 150px;
  height: 100px;
  margin-top: -50px;
  margin-left: -75px;
  background: orange;
}

如果希望写成一个四值简写:

margin: -50px 0 0 -75px;

这种方案依赖子元素的准确宽高,尺寸变化后需要同步修改负外边距。

2. 已知尺寸:使用 calc()

也可以直接计算左上角偏移量:

#child {
  position: absolute;
  top: calc(50% - 50px);
  left: calc(50% - 75px);
  width: 150px;
  height: 100px;
  background: orange;
}

这里的 50px75px 分别是子元素高度和宽度的一半。父元素必须是绝对定位元素的包含块,并且具有明确的可用尺寸。

3. 未知尺寸:使用 transform

如果不知道子元素的宽高,可以使用 transform 的百分比平移。translate() 的百分比相对于元素自身尺寸计算:

#child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: orange;
}

这是一种简洁、常用的未知尺寸居中方案。需要注意,transform 通常只改变视觉位置,不会让普通流中的其他元素重新布局,并且可能创建层叠上下文。

使用 transform 实现居中

4. 绝对定位配合 margin: auto

已知子元素宽高时,可以让四个方向都贴到父元素边界,再使用自动外边距:

#box {
  position: relative;
  width: 300px;
  height: 300px;
  background: #ddd;
}

#child {
  position: absolute;
  inset: 0;
  width: 200px;
  height: 100px;
  margin: auto;
  background: orange;
}

也可以只实现垂直居中:

#child {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 200px;
  height: 100px;
  margin-block: auto;
}

topbottom 通常使用 0。不建议使用 99999px-99999px 等极大值,过度约束可能导致溢出或无法得到预期结果。

如果子元素宽高都是 auto,这种方案的结果会受到内容尺寸和替换元素固有尺寸影响,因此不能把它作为所有未知尺寸元素的通用方案。

四、使用 Flexbox

Flexbox 是现代项目实现水平垂直居中的常用方案:

<div class="container">
  <div class="item">水平垂直居中</div>
</div>
.container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 300px;
  height: 300px;
  background: #ddd;
}

.item {
  background: greenyellow;
}
  • justify-content 控制主轴方向的对齐;
  • align-items 控制交叉轴方向的对齐;
  • 默认 flex-direction: row 时,主轴是水平方向,交叉轴是垂直方向;
  • 父元素必须有可用的高度,垂直居中才有可观察的空间。

如果改变主轴方向:

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 300px;
  height: 300px;
}

此时主轴变为垂直方向,justify-content: center 负责垂直居中,align-items: center 负责水平居中。

使用 margin: auto 的 Flex 写法

Flex 项目也可以通过自动外边距实现双向居中:

.container {
  display: flex;
  width: 100vw;
  height: 100vh;
}

.container > div {
  margin: auto;
}

自动外边距会吸收可用空间,使子元素位于容器中央。原始示例中的 width: 100vw 后缺少分号,已修正。

五、使用 CSS Grid

对于单个元素的水平垂直居中,Grid 可以直接使用:

<div id="box">
  <div class="target">target item</div>
</div>
#box {
  display: grid;
  place-items: center;
  width: 300px;
  height: 300px;
  background: #ddd;
}

.target {
  background: orange;
}

place-items: center 是以下两个属性的简写:

align-items: center;
justify-items: center;

也可以只对目标元素设置:

#box {
  display: grid;
  width: 300px;
  height: 300px;
}

.target {
  place-self: center;
}

现代主流浏览器已经广泛支持 Grid。只有在需要兼容非常旧的浏览器时,才需要额外考虑 fallback。

使用辅助列实现水平居中

如果要保留原文中通过左右辅助元素实现布局的思路,可以使用:

<div id="box">
  <div></div>
  <div class="target">target item</div>
  <div></div>
</div>
#box {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  width: 300px;
  height: 300px;
  background: #ddd;
}

.target {
  justify-self: center;
  background: orange;
}

如果目标元素宽度已知,也可以使用原文中的固定中间列:

#box {
  display: grid;
  grid-template-columns: 1fr 211px 1fr;
  width: 300px;
  height: 300px;
}

.target {
  width: 211px;
  justify-self: center;
  background: orange;
}

在没有内边距、边框和间隙的情况下,两侧列的剩余宽度分别约为:

(300px - 211px) / 2 = 44.5px

不过,对于单个元素居中,直接使用 place-items: center 通常更简单,也不需要额外的辅助元素。

Grid 使用辅助列实现水平居中

Grid 三列等分布局

Grid 固定中间列布局

六、使用 display: table-cell

这是传统项目中常见的兼容方案。父元素设置为表格容器,子元素设置为表格单元格:

<div class="table-box">
  <div class="table-cell">
    <div class="table-content">table-cell 居中</div>
  </div>
</div>
.table-box {
  display: table;
  width: 500px;
  height: 500px;
  background: pink;
}

.table-cell {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

.table-content {
  display: inline-block;
  width: 200px;
  height: 200px;
  background: skyblue;
}

vertical-aligntable-cell 生效,text-align: center 负责单元格内的水平居中。

table-cell 实现文字垂直居中

vertical-align 的适用范围

原文称 vertical-align 只有设置了 HTML valign 属性才有效,这是错误的。CSS vertical-align 可以用于:

  • 行内元素;
  • 行内块元素;
  • 表格单元格;
  • 参与行内格式化或表格布局的盒子。

valign 是传统 HTML 属性,不是 CSS vertical-align 生效的前提。常见取值包括:

  • top:顶部对齐;
  • middle:中线对齐;
  • bottom:底部对齐;
  • baseline:基线对齐。

在表格单元格中,baseline 会让单元格内容按照基线规则参与对齐。基线是文本排版中的一条参考线,不等同于元素的几何中心。

<div class="baseline-table">
  <div class="baseline-cell first">glory</div>
  <div class="baseline-cell second">glad</div>
  <div class="baseline-cell third">align</div>
</div>
.baseline-table {
  display: table;
  width: 300px;
  height: 300px;
  background: #ddd;
}

.baseline-cell {
  display: table-cell;
  vertical-align: baseline;
  border-right: 1px solid orange;
}

.first {
  font-size: 30px;
}

.third {
  font-size: 50px;
}

table-cell 的基线对齐示例

七、使用 line-heightvertical-align 对图片居中

传统写法如下:

.image-box {
  width: 300px;
  height: 300px;
  line-height: 300px;
  text-align: center;
  font-size: 0;
  background: #ddd;
}

.image-box img {
  width: 200px;
  height: 200px;
  vertical-align: middle;
}

这种方法依赖行盒和基线规则,适合维护旧代码。现代项目通常更推荐:

.image-box {
  display: flex;
  align-items: center;
  justify-content: center;
}

八、使用 padding 实现内容周围等距

如果父元素高度由内容自动撑开,可以使用相等的上下内边距:

<div class="padding-box">
  <div class="padding-content">内容</div>
</div>
.padding-box {
  width: 300px;
  padding-block: 100px;
  background: #ddd;
}

.padding-content {
  width: 200px;
  height: 100px;
  background: orange;
}

这种方式是让内容上下的内边距相等,并不是在固定高度的父容器中进行真正的几何居中。父元素通常不能再设置一个与 padding 和内容高度冲突的固定高度,否则会影响预期结果。

九、各种方案的选择

方案尺寸要求适用场景主要注意点
margin: 0 auto块级子元素通常需要宽度水平居中只负责水平方向
text-align: center行内或行内块内容文本、图片、按钮不能直接居中普通块盒
line-height通常适合单行文本旧代码中的单行文本不适合多行文本
负外边距需要知道尺寸传统绝对定位尺寸变化需同步修改
transform不要求知道尺寸绝对定位居中可能创建层叠上下文
position + margin: auto通常需要明确尺寸绝对定位元素需要正确设置 inset
padding父元素高度自动内容上下等距不是固定高度容器居中
Flexbox父元素有可用空间通用水平垂直居中现代项目优先
Grid父元素有可用空间单项或网格布局可使用 place-items
table-cell父元素有宽高传统兼容场景布局语义较旧

十、常见排查问题

1. 垂直居中没有效果

检查:

  • 父元素是否有明确高度或可用高度;
  • Flex 的 align-itemsjustify-content 是否放在正确的轴上;
  • 绝对定位元素的父级是否设置了 position: relative
  • top: 50% 的百分比是否相对于正确的包含块;
  • height: 100% 的父级高度是否确定。

2. transform: translate(-50%, -50%) 为什么可以居中?

top: 50%left: 50% 先把元素的左上角放到父元素中心,translate(-50%, -50%) 再根据元素自身宽高向左、向上移动一半,因此不需要提前知道元素尺寸。

3. 为什么 Grid/Flex 中子元素没有居中?

需要确认:

  • 父元素是否真的有剩余空间;
  • Flex 当前主轴方向是什么;
  • 是否只设置了 align-items 或只设置了 justify-content
  • Grid 是否使用了 place-itemsplace-self 或对应的对齐属性;
  • 子元素是否被 width: 100%align-self: stretch 等规则拉伸。

总结

  • 块级元素水平居中通常使用子元素的 margin: 0 auto
  • 行内元素和行内块元素水平居中通常使用父元素的 text-align: center
  • line-height 适合单行文本,不适合通用垂直居中;
  • 已知尺寸可以使用绝对定位配合负外边距或 calc()
  • 未知尺寸可以使用 positiontransform: translate(-50%, -50%)
  • 绝对定位配合 inset: 0margin: auto 适合尺寸明确的元素;
  • Flexbox 使用 align-items: centerjustify-content: center 是现代常用方案;
  • Grid 可以直接使用 place-items: center
  • vertical-align 不要求 HTML valign 属性,只对合适的行内或表格布局盒生效;
  • 百分比 margin-top 不能用来简单计算子元素高度的一半;
  • padding 方案适合父元素自动撑高的场景,不等于固定高度容器居中;
  • 新项目优先使用 Flexbox 和 Grid,旧方案主要用于兼容和特定布局场景。

参考资料

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS