如何在 flexbox 中垂直对齐文本?

637

我想使用flexbox垂直对齐<li>内的某些内容,但是效果不太好。

我查看了许多在线教程,发现很多教程实际上使用包装器div,该div从父元素的flex设置中获取align-items:center,但我想知道是否有可能省略此额外的元素?

在这种情况下,我选择使用flexbox,因为列表项高度将是动态的%

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

13个回答

830

不要使用align-self: center,而要使用align-items: center

无需更改flex-direction或使用text-align

以下是您的代码,只需要进行一处调整即可使其正常工作:

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  /* align-self: center;    <---- REMOVE */
  align-items: center;   /* <---- NEW    */
  background: silver;
  width: 100%;
  height: 20%;
}

align-self属性适用于 伸缩项。但是您的li不是伸缩项,因为其父元素(ul)没有应用display: flexdisplay: inline-flex

因此,ul不是伸缩容器,li也不是伸缩项,align-self没有效果。

align-items属性类似于align-self,只不过它适用于伸缩容器

由于li是一个伸缩容器,可以使用align-items垂直居中子元素。

* {
  padding: 0;
  margin: 0;
}
html, body {
  height: 100%;
}
ul {
  height: 100%;
}
li {
  display: flex;
  justify-content: center;
  /* align-self: center; */
  align-items: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

codepen演示


在技术上,这是align-itemsalign-self的工作原理...

align-items属性(在容器上)设置align-self的默认值(在项目上)。因此,align-items: center表示所有的弹性项将被设置为align-self: center

但是你可以通过调整单个项目上的align-self来覆盖这个默认值。

例如,您可能希望有相等高度的列,因此容器设置为align-items: stretch。但是,一个项目必须固定在顶部,因此它被设置为align-self: flex-start

示例


文本如何成为弹性项?

有些人可能会想知道如何使一段文本成为一个弹性项...

<li>This is the text</li>

文本之所以成为 li 的子元素,是因为没有被显式包装在内联级别元素中的文本会自动由内联框算法包装成匿名内联元素,并成为其父元素的子元素。

CSS规范指出:

9.2.2.1 匿名内联框

任何直接包含在块级容器元素中的文本都必须被视为匿名内联元素。

弹性盒规范提供了类似的行为。

4. 弹性盒子项

弹性容器中的每个流动子元素都变成了一个弹性盒子项,在弹性容器中直接包含的任何连续文本都会被包装在一个匿名的弹性盒子项中。

因此,li 中的文本是一个弹性盒子项。


4
我喜欢 align-items: baseline。它适用于来自不同Unicode字符的不同高度等情况。 - qräbnö
4
感谢您解释并链接到匿名内联盒子的概念……这真的有助于澄清为什么通过试错法可以实现某些效果的工作方式。 - squarecandy
不要忘记删除任何 margin: 0px; - Adam Cox

87
最好的方法是在一个弹性盒子内部嵌套另一个弹性盒子。只需给子元素添加 "align-items: center" 样式即可使文本在其父级元素中垂直居中。
// Assuming a horizontally centered row of items for the parent but it doesn't have to be
.parent {
  align-items: center;
  display: flex;
  justify-content: center;
}

.child {
  display: flex;
  align-items: center;
}

2
如果你想要一个完美居中的文本,仅使用 text-align:center 是不够的。你需要同时使用 align-items: center - Tzwenni
我猜想如果你给带有"display: flex"属性的父元素设置 "align-items: center", 那么它会自动应用到所有子元素上,因此不必为每个子元素显式地声明 "align-items: center". - Chandra Agarwala
1
@ChandraAgarwala - 这是正确的,但如果你想要垂直居中每个子元素的内容,你还需要为每个子元素添加另一个 display: flex; align-items: center; - serraosays

57

最受欢迎的答案是解决了原帖中特定问题的答案,其中内容(文本)被包裹在一个内联块元素中。有些情况可能是关于将普通元素垂直居中在容器中,这也适用于我的情况,因此你所需要做的就是:

align-self: center;

38

不会写答案,因为已经有很多人给出了正确的答案。然而,我想要向你展示一个有用的工具,可以在将来帮助你避免这样的问题。

在你的浏览器开发者工具中,你需要检查具有display: flex属性的一个元素,然后点击截图中显示的图标。

enter image description here

您随后将看到选择一些属性的选项,以便于display:flex,这样您可以快速检查所有选项,而不需要知道您可以使用什么。


4
这非常有用。只是需要注意的是,它似乎不适用于Firefox,而是适用于Chrome浏览器。 - nck
这是我在SO上看到的最有用的答案! - John
可能有更多有用的答案,但还是谢谢! - Krzysztof Antosik

13

结果

enter image description here

HTML

<ul class="list">
  <li>This is the text</li>
  <li>This is another text</li>
  <li>This is another another text</li>
</ul>
使用align-items替代align-self,同时我还将flex-direction添加为column
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

.list {
  display: flex;
  justify-content: center;
  flex-direction: column;  /* <--- I added this */
  align-items: center;   /* <--- Change here */
  height: 100px;
  width: 100%;
  background: silver;
}

.list li {  
  background: gold;
  height: 20%; 
}

11

li 的显示设置为 flex,并将 align-items 设置为 center

li {
  display: flex;

  /* Align items vertically */
  align-items: center;

  /* Align items horizontally */
  justify-content: center;

}

我个人也会针对伪元素使用border-box (通用选择器*和伪元素)。

*,
*::before,
*::after {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
  

7
使用display: flex可以控制HTML元素的垂直对齐方式。

.box {
  height: 100px;
  display: flex;
  align-items: center; /* Vertical */
  justify-content: center; /* Horizontal */
  border:2px solid black;
}

.box div {
  width: 100px;
  height: 20px;
  border:1px solid;
}
<div class="box">
  <div>Hello</div>
  <p>World</p>
</div>


6

align-self 属性并不是用来对 li 元素内部的项目进行对齐,而是用来对整个 li 元素进行对齐的。

Using align-items would aling the text inside the li. Check out this code. It works.

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-items: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>


4

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

.flex-child {
  display: flex;
  width: 100%;
  background-color: khaki;
  border: 1px solid #000;
  align-items: center;
  justify-content: center;
  height: 100px;
  margin: 10px;
  padding: 10px;
}
<div class="container flex-container">
  <div class="flex-child item-1">English</div>
  <div class="flex-child item-2"> English</div>
  <div class="flex-child item-3"> English</div>
</div>


4

这取决于你的行高,只需要调用另一项行高即可。

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 100%;
  height:50px;line-height:50px;
}
<ul>
  <li>This is the text</li>
</ul>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接