vertical-align 属性 是如何工作的?

How does the vertical-align property work?

我不明白 vertical-align 什么时候可以,什么时候不能。

每次我 运行 进入 vertical-align 的用例时,似乎都在掷硬币,看它是否真的有效。我知道它必须应用于内联元素。我读到我必须为通常没有的元素指定 line-height。我读到 height 属性 必须有一个静态 (non-auto/non-%) 值。我读过一些(现代)浏览器如果使用的元素不是自然的内联元素,则无法正确处理 vertical-align 。我不清楚 vertical-align 应该在包含元素上(如 text-align)还是我想要垂直对齐的元素。

我创建了 this jsfiddle 来尝试解决问题,但仍然感到困惑。

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  width: 400px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  display: inline-block;
  height: 200px;
  vertical-align: middle;
}
    
#header {
  border: green 1px solid;
  display: inline-block;
  line-height: 1em;
  margin: 0;
}
<div id="outer">
  <div id="inner">
    <h1 id="header">
      Some Text
    </h1>
  </div>
</div>

在上面的 jsfiddle 中,我希望 #header 位于 #outer#inner 顶部和底部的中间位置。显然,事实并非如此。

简单的说:vertical-align只有当它应用到的元素有display: inline-blockìnline时才active/valid,例如,如果你想对齐,这很有用顶部边框处的一堆图像:您将它们定义为 inline-blocks 并将 vertical-align: top 应用到它们

这是一个例子:

.wrapper {
  height: 250px;
  border: 1px solid green;
}

.wrapper>img {
  display: inline-block;
  vertical-align: top;
}
<div class="wrapper">
  <img src="https://placehold.it/120x40">
  <img src="https://placehold.it/70x140">
  <img src="https://placehold.it/80x60">
  <img src="https://placehold.it/60x140">
</div>

在您的 fiddle 中,元素相互嵌套,而不是彼此相邻,即它们不是兄弟姐妹 - 每个元素只有一个子元素,因此没有像上面的例子。

理解为什么添加多行文本不起作用的最简单方法,因为垂直对齐将在各自的行(行框)上对齐,而不是像您想象的那样在整个容器上对齐。

因此,如果我们添加更多文本,我们将得到以下内容。

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  width:180px;
  display: inline-block;
  overflow:hidden;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:middle;">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:top;">
      Some Text Some Text Some Text
    </h1>
  </div>
</div>

基本上没有对齐的地方,所有的对齐几乎都是等价的,因为文本定义了line-box,因此它的高度等于line box的高度,没有对齐的空间。

现在让我们增加行的高度(使用行高)

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  width:180px;
  line-height:200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
  line-height:1em;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:middle;">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:top;">
      Some Text Some Text Some Text
    </h1>
  </div>
</div>

看看每行现在变大了,每个文本都在各自的行上对齐,高度为 200px,我们可以清楚地看到对齐方式有何不同。

在这种情况下,文本有足够的空间可以按照您的意愿对齐,如果我们只保留一行文本,我们就会看到神奇的效果:

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  line-height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
  line-height:1em;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:middle">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:top">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:bottom">
      Some Text
    </h1>
  </div>
</div>

您可能还会注意到 middlebaseline 非常接近,因为:

Aligns the middle of the element with the baseline plus half the x-height of the parentref

只差一半x-height

另一个需要注意的重要事实是,如果我们不为行内元素设置行高,这个元素将继承其父元素的行高,并且像 top 这样的对齐方式将没有任何效果.

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  line-height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:middle">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:top">
      Some Text
    </h1>
  </div>
</div>

Aligns the top of the element and its descendants with the top of the entire line.

具有相同的行高意味着该元素已经位于行框的顶部和底部,因此 top bottom 将表现得像基线(默认值)。


line-box的高度也可以通过元素的高度来控制。您可能为一个元素设置了较大的字体大小,这将使行的高度更大,并且有足够的空间在同一个行框中对齐其旁边的小文本:

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
@keyframes change {
  from {font-size:20px;}
  to {font-size:100px;}
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Text
    </h1>
    <h1 class="header" style="font-size:100px;animation:change 5s linear alternate infinite">
      T
    </h1>
    <h1 class="header" style="vertical-align:middle;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:top;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:bottom;">
      Text
    </h1>
  </div>
</div>

你也可以通过设置inline-block元素的高度来控制line box:

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
.elem {
 display:inline-block;
 background:red;
 width:2px;
 height:5px;
 animation:change 5s linear alternate infinite;
}
@keyframes change {
  from {height:20px;}
  to {height:100px;}
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Text
    </h1>
    <div class="elem">
    </div>
    <h1 class="header" style="vertical-align:middle;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:top;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:bottom;">
      Text
    </h1>
  </div>
</div>

作为结论: 要使用 vertical-align 对齐,您应该有一个高度足够大的行框(明确设置或由其他元素设置)可以对齐你的元素。如果您的元素正在定义行框(这是常见的情况),则没有任何内容需要对齐。


一些好问题需要更多的细节:

My inline-block elements are not lining up properly

Why is this inline-block element pushed downward?