Menu

CSS 如何让 div 居中:所有方法实测对比

让 div 水平居中、垂直居中或同时居中的所有方法:flexbox、grid、margin auto、absolute 定位加 transform、inset 加 margin auto,以及 align-content。每种方法都能实时运行并测量自己的居中效果,另附一张表告诉你什么时候用哪种。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

简短的回答

要让 div 在父元素中水平和垂直同时居中,就把父元素设为 grid,再让它的内容居中:

.parent {
  display: grid;
  place-items: center;
  min-height: 200px; /* the parent needs room to center in */
}

子元素多大都可以,而且子元素本身什么都不用写。下面把六种方法放在一起对比。每个盒子渲染后都会测量自己,并打印出它的中心离父元素中心有多远:

六种方法在两个方向上都报告 0px(舞台的 1px 边框四边相等,所以不会让中心偏移)。改一下某个盒子的宽度或文字再运行一次:不依赖固定尺寸的方法仍然是 0。

该用哪种方法

方法居中方向子元素需要固定尺寸吗?最适合
Grid place-items: center两个方向不需要默认选择:盒子里只有一个子元素
Flexbox justify-content + align-items两个方向不需要一行或一列项目,作为一组居中
flex 或 grid 父元素中的 margin: auto两个方向不需要让一个项目居中,而它的兄弟元素按别的方式排列
margin: 0 auto仅水平需要 width 或 max-width正常流中的页面容器、文章、表单
Absolute + translate(-50%, -50%)两个方向不需要盖在其他内容上面的遮罩、徽标和弹窗
Absolute + inset: 0; margin: auto两个方向需要,宽度和高度固定尺寸的对话框
块元素上的 align-content: center垂直不需要不改变父元素 display 的垂直居中

方法 1:flexbox

Flexbox 用两个属性在两个轴上居中。justify-content 负责主轴(在一行中就是水平方向),align-items 负责交叉轴:

有多个子元素时,flexbox 会把它们作为一组居中,并保持排成一行。这正是它胜过 grid 的地方:grid 会把三个项目叠成居中的一列。justify-content 页面讲解了所有对齐值。

方法 2:grid

place-items: center 是 align-items: center 加 justify-items: center 的简写。在只有一个子元素的 grid 容器上,它会让这个子元素在两个方向上都居中:

用 min-height 而不是 height,这样卡片高于 180px 时父元素会跟着变高,卡片不会溢出。

方法 3:margin: 0 auto(水平居中)

宽度小于容器的块元素,可以用自动的左右外边距实现水平居中。浏览器会把剩余空间平均分给两边:

第二个盒子占满了整行宽度,没有剩余空间,所以什么都没有移动。这就是 margin: 0 auto“不起作用”最常见的原因。另外它在正常流中只能水平居中,垂直方向的 auto 外边距在那里会变成 0。不过在 flex 或 grid 父元素中,margin: auto 会在两个方向上都居中,也就是上面对比中的第三个盒子。

方法 4:absolute 定位加 transform

当元素必须盖在其他内容上面时(照片上的徽标、页面上的弹窗),把它绝对定位到 50% 的位置,再往回拉自身尺寸的一半:

top: 50%; left: 50% 把元素的左上角放到中心点。translate() 中的百分比是相对元素自身尺寸的,所以无论宽高是多少,-50% 都会把它往回移动自身宽高的一半。父元素必须是定位元素(position: relative),否则元素会相对整个页面居中。定位的内容见 position 页面。

已知尺寸的元素还有一种写法:position: absolute; inset: 0; margin: auto;,再加上 width 和 height。自动外边距会在四个方向上平分空间。

方法 5:普通块元素上的 align-content

align-content: center 现在也能用在普通的块容器上,不再只限于 flex 和 grid 容器。它让内容垂直居中,而不改变子元素的布局方式:

.parent {
  min-height: 200px;
  align-content: center;   /* vertical centering, still display: block */
}
.child {
  max-width: 300px;
  margin-inline: auto;     /* horizontal centering */
}

当前版本的 Chrome、Firefox 和 Safari 都支持它。旧浏览器会忽略它,所以如果必须兼容旧浏览器,就用 grid。

在整个屏幕中居中

要让对话框在视口中居中,而且不受滚动影响,就把一个固定定位的全屏图层和 grid 结合起来:

.overlay {
  position: fixed;
  inset: 0;                     /* covers the viewport */
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / 50%);
}

要让整个页面的内容垂直居中,在父元素上用 min-height: 100dvh,而不是 100vh:在手机上,100vh 包含了浏览器工具栏后面的区域,所以“中心”会偏低。

让文字居中是另一回事

上面的方法都是让一个盒子居中。要让盒子里的文字居中,就在盒子上用 text-align: center,详见 HTML 文字居中页面。很多时候两者都需要:用 grid 让卡片居中,再用 text-align 让卡片里的每一行居中。

常见错误

  • 父元素没有高度。 垂直居中需要剩余空间,而高度随内容收缩的父元素没有剩余空间。
  • 在占满整行的块元素上用 margin: 0 auto。 先给它设置 width 或 max-width。
  • 在正常流中用 margin: auto 垂直居中。 正常流中垂直方向的自动外边距是 0,请用 flex 或 grid。
  • 绝对定位居中,但父元素不是定位元素。 元素会在页面中居中,而不是在盒子里。
  • 把 align-items: center 写在子元素上。 对齐属性要写在父元素(flex 或 grid 容器)上,margin: auto 和 align-self 除外。
  • 用 text-align: center 让块元素居中。 它居中的是行内内容(文字、图片、inline-block 子元素),而不是块级子元素。

常见问题

如何让 div 水平和垂直同时居中?

把父元素设为 grid 并让内容居中:.parent { display: grid; place-items: center; }。flexbox 的写法是 display: flex; justify-content: center; align-items: center;。无论哪种写法,父元素的高度都要比 div 高。

如何只让 div 水平居中?

给它设置宽度和自动的左右外边距:.box { width: 300px; margin: 0 auto; }(响应式的块可以用 max-width)。margin-inline: auto 是同一件事的逻辑属性写法。

为什么 margin: 0 auto 不能让我的 div 居中?

这个 div 的宽度并不比容器小,所以没有可以分配的剩余空间(块元素默认占满整行宽度)。设置 width 或 max-width 即可。它对行内元素也不起作用,在正常流中也永远不会垂直居中。

为什么我的 div 不能垂直居中?

父元素的高度只等于内容的高度,没有多余的空间可以居中。给父元素设置一个高度(或 min-height),再用 grid 或 flexbox 居中。

让 div 居中最简单的方法是什么?

在父元素上写 display: grid; place-items: center;:两条声明,两个方向,子元素多大都行。如果父元素还要把其他项目排成一行,就用 flexbox。

如何让 div 里的文字居中?

在 div 上用 text-align: center,它作用于文字和行内内容。让 div 本身居中和让 div 里的文字居中是两件不同的事。

Coddy 编程语言插图

和 Coddy 一起学编程

开始