CSS 中的居中指南

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

在 CSS 中居中元素是 CSS 吐槽的典型代表。为什么它必须如此困难? 他们嘲讽道。我认为问题不在于它难以实现,而在于有太多不同的方法可以实现它,具体取决于情况,很难知道该选择哪一种。

所以让我们把它变成一棵决策树,希望能够简化操作。

我需要居中…

水平方向

它是内联元素还是内联-*元素(如文本或链接)?

您可以使用以下方法水平居中内联元素,在块级父元素内:

.center {
  text-align: center;
}

这适用于内联、内联块、内联表格、内联弹性盒等。

它是一个块级元素吗?

您可以通过为块级元素设置margin-leftmargin-rightauto来居中(并且它具有设定的width,否则它将是全宽并且不需要居中)。这通常使用以下简写方式完成

.center-me {
  margin: 0 auto;
}

无论您要居中的块级元素的宽度或父元素如何,这都适用。

请注意,您不能将元素float到中心。不过有一个技巧。

是否有多个块级元素?

如果您有两个或多个需要水平一行居中的块级元素,则您最好将它们设置为不同的display类型。这是一个将它们设置为inline-block的示例,以及一个flexbox的示例

除非您的意思是您有多个垂直堆叠的块级元素,在这种情况下,自动边距技术仍然适用

垂直方向

在 CSS 中,垂直居中稍微复杂一些。

它是内联元素还是内联-*元素(如文本或链接)?
它是一行吗?

有时,内联/文本元素可能看起来是垂直居中的,仅仅是因为它们的上方和下方有相等的填充。

.link {
  padding-top: 30px;
  padding-bottom: 30px;
}

如果由于某种原因填充不是一种选择,并且您试图居中一些您知道不会换行的文本,则有一个技巧是使line-height等于高度,这将center文本。

.center-text-trick {
  height: 100px;
  line-height: 100px;
  white-space: nowrap;
}
它有多行吗?

顶部和底部的相等填充也可以为多行文本提供居中效果,但如果这不起作用,也许包含文本的元素可以是表格单元格,无论是字面上的还是使用 CSS 使其表现得像一个表格单元格。vertical-align 属性处理这种情况,在这种情况下,与它通常处理一行上对齐的元素的对齐方式不同。(更多信息。

如果表格式方法不可行,也许您可以使用flexbox?可以很容易地使单个flex-child在flex-parent中居中。

.flex-center-vertically {
  display: flex;
  justify-content: center;
  flex-direction: column;
  height: 400px;
}

请记住,只有当父容器具有固定高度(px、% 等)时,这才是真正相关的,这就是为什么此处的容器具有高度的原因。

如果这两种技术都不可行,您可以采用“幽灵元素”技术,其中一个全高伪元素放置在容器内,并且文本与此伪元素垂直对齐。

.ghost-center {
  position: relative;
}
.ghost-center::before {
  content: " ";
  display: inline-block;
  height: 100%;
  width: 1%;
  vertical-align: middle;
}
.ghost-center p {
  display: inline-block;
  vertical-align: middle;
}
它是一个块级元素吗?
您知道元素的高度吗?

在网页布局中,不知道高度的情况相当常见,原因有很多:如果宽度发生变化,文本重排可能会改变高度。文本样式的变化可能会改变高度。文本数量的变化可能会改变高度。具有固定纵横比的元素(如图像)在调整大小时可能会改变高度。等等。

但是,如果您知道高度,则可以像这样垂直居中

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  height: 100px;
  margin-top: -50px; /* account for padding and border if not using box-sizing: border-box; */
}
元素的高度未知吗?

仍然可以通过在向下移动一半高度后将其向上移动一半高度来居中它

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
您是否关心元素是否会拉伸容器的高度?

如果您不关心,您只需要将内容垂直居中,使用表格或 CSS 显示将元素变成表格可以解决问题。

您可以使用flexbox吗?

毫不奇怪,这在flexbox中容易得多。

.parent {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

您还可以使用子元素上的margin: auto;在flexbox中实现居中。

水平和垂直方向

您可以以任何方式组合上述技术来获得完美居中的元素。但我发现这通常分为三大类

元素的宽度和高度是固定的吗?

在您将其绝对定位在 50% / 50% 之后,使用等于该宽度和高度一半的负边距可以将其居中,并具有良好的跨浏览器支持

.parent {
  position: relative;
}

.child {
  width: 300px;
  height: 100px;
  padding: 20px;

  position: absolute;
  top: 50%;
  left: 50%;

  margin: -70px 0 0 -170px;
}
元素的宽度和高度未知吗?

如果您不知道宽度或高度,则可以使用transform属性和两个方向上的负translate 50%(它基于元素的当前宽度/高度)来居中

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
您可以使用flexbox吗?

要使用flexbox在两个方向上居中,您需要使用两个居中属性

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}
您可以使用网格吗?

这只是一个小的技巧(由 Lance Janssen 发送),它几乎适用于一个元素

body, html {
  height: 100%;
  display: grid;
}
span { /* thing to center */
  margin: auto;
}

结论

您完全可以在 CSS 中居中元素。