Vertical-Align: All You Need To Know (CSS)
垂直对齐:您需要知道的所有内容(CSS)

  
We need to talk about this!

Yep, let’s talk about the CSS property vertical-align. It’s intended use is to align text and elements next to each other. Like centering an icon next to a bit of text.
好的,让我们谈谈 CSS 属性vertical-align。它的预期用途是将文本和元素彼此对齐。就像在文本旁边居中一个图标

But, it can be a real scumbag sometimes with all its seemingly mysterious rules at work. For example, it might happen, that the element you changed vertical-align for doesn’t change its alignment at all, but other elements next to it do! What a joy!
但是,有时它可能真的是个令人讨厌的家伙,因为工作中有很多看似神秘的规则。例如,可能发生您更改的元素 vertical-align 根本没有改变其对齐方式,而旁边的其他元素却发生了变化!真是让人开心!

So, to minimize future pain, I waded through W3C’s CSS specifications to clarify the behavior of vertical-align once and for all.
因此,为了减少未来的痛苦,我深入研究了 W3C 的 CSS规范,以便 彻底澄清 vertical-align 的行为

Let’s tackle the rules of the game!
让我们来应对游戏规则吧!

What you will learn in this article:
您将在本文中学习到的内容:

  1. Vertical-Align Acts On Inline-level Elements In a Line Box.
    垂直对齐作用于行框中的行内元素。
  2. Inline-level Elements and Line Boxes Have Baselines, Tops and Bottoms.
    行内元素和行框具有基线、顶部和底部。
  3. Vertical-Align Aligns Baselines, Tops and Bottoms.
    垂直对齐对齐基线、顶部和底部。
  4. Example: How to center an icon next to a bit of text.
    示例:如何将图标居中放置在一小段文本旁边。
  5. Example: How the baseline might move.
    示例:基线可能如何移动。
  6. Example: How to vertically center elements without a gap at the bottom.
    示例:如何在不留底部间隙的情况下垂直居中元素。
  7. Example: How to remove the gap between two aligned elements.
    示例:如何移除两个对齐元素之间的间隙。

Vertical-Align Acts On Inline-Level Elements In a Line Box
垂直对齐作用于行框中的行内级元素

vertical-align is used to align inline-level elements. These are elements, whose display property evaluates to
vertical-align 用于对齐 行内级元素。这些元素的 display 属性的值为

  • inline, 内联,
  • inline-block or inline-block 或
  • inline-table (not considered in this article).
    行内表(在本文中不予考虑)。

Inline elements are basically tags wrapping text.
行内元素 基本上是包裹文本的标签。

Inline-block elements are what their name suggests: block elements living inline. They can have a width and height (possibly defined by its own content) as well as padding, a border and margin.
行内块元素顾名思义,就是在行内居住的块元素。它们可以有宽度和高度(可能由其自身内容定义),以及内边距、边框和外边距。

Inline-level elements are laid out next to each other in lines. Once there are more elements than fit into the current line, a new line is created beneath it. All these lines have a so-called line box, which encloses all the content of its line. Differently sized content means line boxes of different height. In the following illustration the top and bottom of line boxes are indicated by red lines.
内联级元素并排排列在一起。 一旦元素数量超过当前行的容纳量,就会在其下方创建新行。 所有这些行都有一个所谓的 行框,该框包含其行的所有内容。 不同大小的内容意味着行框的高度不同。 在下面的插图中,行框的顶部和底部用红线表示。

  
A tall in a line of text.
A short in a line of text.
This can happen.

The line boxes trace out the field we are playing on. Inside these line boxes the property vertical-align is responsible for aligning the individual elements. So, in respect to what are elements aligned?
线框描绘了我们正在玩的场地。在这些线框内,属性 vertical-align 负责对齐各个元素。那么,元素是相对于什么对齐的?

About Baselines, Tops and Bottoms
关于基线、顶部和底部

The most important reference point to align vertically is the baseline of the involved elements. In some cases the top and bottom edge of the elements’ enclosing box becomes important, too. Let’s have a look where the baseline and outer edges live for each involved type of element:
对齐的最重要参考点是相关元素的基线。在某些情况下,元素外包围框的上下边缘也变得重要。让我们来看看每种相关元素的基线和外边缘的位置:

Inline Element 行内元素

  
aAÄ qQ
aAÄ qQ
aAÄ qQ

Here you see three lines of text next to each other. The top and bottom edge of the line height is indicated by red lines, the height of the font by green lines and the baseline by a blue line. On the left, the text has a line height set to the same height as the font-size. The green and red line collapsed to one line on each side. In the middle, the line height is twice as large as the font-size. On the right, the line height is half as large as the font-size.
在这里,您看到三行文本并排放置。行高的顶部和底部边缘由红线表示,字体的高度由绿线表示,基线由蓝线表示。在左侧,文本的行高设置为与字体大小相同的高度。绿色和红色的线在每一侧合并为一条线。中间,行高是字体大小的两倍。在右侧,行高是字体大小的一半

The inline element’s outer edges align themselves with the top and bottom edge of its line height. It does not matter, if the line height is smaller than the height of the font. So, the outer edges are the red lines in the figure above.
行内元素的外边缘 与其行高的顶部和底部边缘对齐。它 并不 重要,如果行高小于字体的高度。那么,外边缘就是上面图中的红线。

The inline element’s baseline is the line, the characters are sitting on. This is the blue line in the figure. Roughly speaking, the baseline is somewhere below the middle of the font’s height. Have look at the W3C Specs for a detailed definition.
行内元素的基线是字符所处的线,即坐落的地方。这是图中的蓝线。大致来说,基线是字体高度中间以下的某个位置。查看 W3C 规范以获取详细定义

Inline-Block Element 内联块元素

  
c
c

From left to right you see: an inline-block element with in-flow content (a “c”), an inline-block element with in-flow content and overflow: hidden and an inline-block element with no in-flow content (but the content area has a height). The boundaries of the margin is indicated by red lines, the border is yellow, the padding green and the content area blue. The baseline of each inline-block element is shown as a blue line.
从左到右,您看到的是:一个包含内联内容的内联块元素(一个“c”),一个包含内联内容和overflow: hidden的内联块元素,以及一个没有内联内容的内联块元素(但内容区域有高度)。边距的边界由红线表示,边框为黄色,内边距为绿色,内容区域为蓝色。每个内联块元素的基线以蓝线表示。

The Inline-block element’s outer edges are the top and bottom edge of its margin-box. These are the red lines in the figure.
行内块元素的外边缘是其 外边框 的上下边缘。这些是图中的红线。

The Inline-block element’s baseline depends on whether the element has in-flow content:
行内块元素的基线 取决于该元素是否具有流内内容:

  • In case of in-flow content the baseline of the inline-block element is the baseline of the last content element in normal flow (example on the left). For this last element its baseline is found according to its own rules.
    在流入内容的情况下,行内块元素的基线是正常流中最后一个内容元素的基线(左侧示例)。对于这个最后的元素,其基线是根据其自身的规则确定的。
  • In case of in-flow content but an overflow property evaluating to something other than visible, the baseline is the bottom edge of the margin-box (example in the middle). So, it is the same as the inline-block element’s bottom edge.
    在出现流入内容但 overflow 属性计算为非 visible 的情况下,基线是边距框的底边(中间的例子)。因此,它与内联块元素的底边相同。
  • In case of no in-flow content the baseline is, again, the bottom edge of the margin-box (example on the right).
    在没有内联内容的情况下,基线再次是边距框的底部边缘(右侧示例)。

Line Box 线框

    
x This can happen.

You’ve already seen this setting above. This time I drew in the top and bottom of the line box’s text box (green, more on this below) and the baseline (blue), too. I also highlighted the area of the text elements by giving them a grey background.
您已经在上面看到过这个设置。这次我绘制了线框文本框的顶部和底部(绿色,下面会详细说明)以及基线(蓝色)。我还通过给文本元素添加灰色背景来突出显示它们的区域。

The line box has a top edge aligned to the top edge of the top-most element of this line and a bottom edge aligned to the bottom edge of the bottom-most element of the line. This is the box indicated by the red lines in the figure above.
该行框有一个上边缘与该行最顶部元素的上边缘对齐,以及一个下边缘与该行最底部元素的下边缘对齐。这就是上图中红线所指示的框。

The line box’s baseline is variable:
线框的基线是可变的:

CSS 2.1 does not define the position of the line box's baseline.
CSS 2.1 没有定义行框的基线位置。

This is probably the most confusing part, when working with vertical-align. It means, the baseline is placed where ever it needs to be to fulfil all other conditions like vertical-align and minimizing the line box’s height. It is a free parameter in the equation.
这可能是使用垂直对齐时最令人困惑的部分。它意味着基线被放置在需要的位置,以满足所有其他条件,如垂直对齐和最小化行框的高度。它是方程中的一个自由参数。

Since the line box’s baseline is invisible, it may not immediately be obvious where it is. But, you can make it visible very easily. Just add a character at the beginning of the line in questions, like I added an “x” in the figure. If this character is not aligned in any way, it will sit on the baseline by default.
由于线框的基线是不可见的,因此可能不立即显而易见它的位置。但是,您可以很容易地使其可见。只需在所需行的开头添加一个字符,就像我在图中添加的“x”一样。如果这个字符没有以任何方式对齐,它将默认位于基线上。

Around its baseline the line box has what we might call its text box. The text box can simply be thought of as an inline element inside the line box without any alignment. Its height is equal to the font-size of its parent element. Therefore, the text box only just encloses the unformatted text of the line box. The box is indicated by the green lines in the figures above. Since this text box is tied to the baseline, it moves when the baseline moves. (Side note: this text box is called strut in the W3C Specs)
在基线周围,行框有我们可以称之为其 文本框 的内容。文本框可以简单地认为是行框内的一个行内元素,没有任何对齐。它的高度等于其父元素的字体大小。因此,文本框仅仅包围了行框的未格式化文本。该框在上面的图中用绿色线条表示。由于这个文本框与基线相连,因此当基线移动时,它也会随之移动。(附注:在 W3C 规范中,这个文本框被称为 支撑

Phew, this was the hard part. Now, we know everything to put things into perspective. Let’s quickly sum up the most important facts:
哇,这才是难点。现在,我们知道一切以便进行正确的评估。让我们快速总结一下最重要的事实:

  • There is an area called line box. This is the area in which vertical alignment takes place. It has a baseline, a text box and a top and bottom edge.
    有一个区域叫做行框。这是进行垂直对齐的区域。它有一个基线,一个文本框,以及顶部底部边缘
  • There are inline-level elements. These are the objects that are aligned. They have a baseline and a top and bottom edge.
    内联级元素。这些是对齐的对象。它们有一个基线,以及一个顶部底边

Vertical-Align Aligns Baselines, Tops and Bottoms
垂直对齐对齐基线、顶部和底部

By using vertical-align the reference points mentioned in the list above are set into a certain relationship.
通过使用 vertical-align,上述列表中的参考点被设置为某种关系。

Aligning Relative To the Line Box’s Baseline
相对于行框基线对齐

    
         x
            baseline
             sub
             super
             -50%
             +10px
        
    
  • baseline: The element’s baseline sits exactly on top of the line box’s baseline.
    基线: 元素的基线正好位于行框的基线上。
  • sub: The element’s baseline is shifted below the line box’s baseline.
    sub:该元素的基线被移动到线框基线的下方。
  • super: The element’s baseline is shifted above the line box’s baseline.
    super: 元素的基线被移到行框的基线之上。
  • <percentage>: The element’s baseline is shifted with respect to the line box’s baseline by a percentage relative to the line-height.
    <percentage>: 元素的基线相对于行框的基线按行高的百分比偏移。
  • <length>: The element’s baseline is shifted with respect to the line box’s baseline by an absolute length.
    <length>: 元素的基线相对于行框的基线按绝对长度进行了偏移。

The Special case vertical-align: middle deserves its own figure:
特殊情况 vertical-align: middle 值得单独列出:

    
          x
              middle
            
        
    
  • middle: The midpoint between the element’s top and bottom edge is aligned to the line box’s baseline plus half of the x-height.
    中间: 元素的顶部和底部边缘之间的中点与行框的基线对齐,加上 x 高度的一半。

Aligning Relative To the Line Box’s Text Box
相对于行框的文本框对齐

    
            x
        
              text-top
            
              text-bottom
            
        
    

One could also list these two cases under aligning relative to the line box’s baseline, since the position of the text box is determined by the baseline.
这两种情况也可以归类为相对于线框基线的对齐,因为文本框的位置是由基线决定的。

  • text-top: The element’s top edge is aligned to the line box’s text box top edge.
    text-top:元素的顶部边缘与行框的文本框顶部边缘对齐。
  • text-bottom: The element’s bottom edge is aligned to the line box’s text box bottom edge.
    text-bottom:元素的底边对齐到行框的文本框底边。

Aligning Relative To the Line Box’s Outer Edges
相对于行框的外边缘对齐

    
            x
        
              top
            
              bottom
            
        
    
  • top: The element’s top edge is aligned to the line box’s top edge.
    顶部:元素的上边缘与行框的上边缘对齐。
  • bottom: The element’s bottom edge is aligned to the line box’s bottom edge.
    底部:元素的底边与行框的底边对齐。

The formal definition is found in, of course, the W3C Specs.
正式定义可以在 W3C 规范中找到。

Why Vertical-Align Behaves The Way It Behaves
垂直对齐为什么会这样表现

We can now take a closer look at vertical alignment in certain situations. Especially, we will deal with situations where things might have gone wrong.
我们现在可以更仔细地观察某些情况下的垂直对齐。特别是,我们将处理一些可能出现问题的情况。

Centering an Icon 居中图标

One question bugging me was the following: I have an icon I want to center next to a line of text. Just giving the icon a vertical-align: middle didn’t seem to center it in a satisfying way. Have a look at this example:
有一个问题让我困扰,那就是:我有一个图标想要在一行文字旁边居中。仅仅给图标添加 vertical-align: middle 似乎并不能令人满意地将其居中。请看这个例子:

  
Centered?
Centered!
<!-- left mark-up -->
<span class="icon middle"></span>
Centered?

<!-- right mark-up -->
<span class="icon middle"></span>
<span class="middle">Centered!</span>

<style type="text/css">
  .icon   { display: inline-block;
            /* size, color, etc. */ }

  .middle { vertical-align: middle; }
</style>

Here is the example again, but I drew in some auxiliary lines you already know from above:
这里是又一个例子,但我添加了一些你已经知道的辅助线:

  
x Centered?
Centered!

This sheds some light on our matter. Because the text on the left isn’t aligned at all, it sits on the baseline. The thing is, by aligning the box with vertical-align: middle we are aligning it to the middle of the lower case letters without ascenders (half of the x-height). So, characters with ascenders stand out at the top.
这为我们的事务提供了一些启示。因为左侧的文本根本没有对齐,它位于基线。问题是,通过使用 vertical-align: middle 对齐框,我们将其对齐到没有上升音符的小写字母的中间(x-height 的一半)。因此,带有上升音符的字符在顶部突出显示。

On the right, we take the whole area of the font and align its midpoint vertically, too. The text’s baseline shifts slightly below the line box’s baseline to achieve this. The Result is a nicely centered text next to an icon.
在右侧,我们将字体的整个区域对齐到其中点的垂直方向。文本的基线稍微下移到行框的基线以下,以实现这一点。结果是文本与图标之间居中对齐。

Movement Of the Line Box’s Baseline
线框基线的移动

This is a common pitfall when working with vertical-align: The position of the line box’s baseline is affected by all elements in that line. Let’s assume, an element is aligned in such a way, that the baseline of the line box has to move. Since most vertical alignment (except top and bottom) is done relative to this baseline, this results in an adjusted position of all other elements in that line, too.
这是在处理vertical-align时常见的陷阱:行框的基线位置受到该行中所有元素的影响。假设有一个元素的对齐方式导致行框的基线必须移动。由于大多数垂直对齐(除了顶部和底部)都是相对于这个基线进行的,这也会导致该行中所有其他元素的位置调整。

Some Examples: 一些示例:

  • If there is a tall element in the line spanning across the complete height, vertical-align has no effect on it. There is no space above its top and below its bottom, that would let it move. To fulfil its alignment relative to the line box's baseline, the line box's baseline has to move. The short box has a vertical-align: baseline. On the left, the tall box is aligned text-bottom. On the right, it is aligned text-top. You can see the baseline jumping up taking the short box with it.
    如果在行中有一个高的元素占据整个高度,vertical-align 对它没有效果。它的顶部和底部没有空隙可以让它移动。为了使其相对于行框的基线对齐,行框的基线必须移动。短框有一个 vertical-align: baseline。左侧,高框对齐 text-bottom。右侧,它对齐 text-top。你可以看到基线向上跳,带着短框一起移动。

          
    <!-- left mark-up -->
    <span class="tall-box text-bottom"></span>
    <span class="short-box"></span>
    
    <!-- right mark-up -->
    <span class="tall-box text-top"></span>
    <span class="short-box"></span>
    
    <style type="text/css">
      .tall-box,
      .short-box   { display: inline-block;
                    /* size, color, etc. */ }
    
      .text-bottom { vertical-align: text-bottom; }
      .text-top    { vertical-align: text-top; }
    </style>

    The same behaviour shows up when aligning a tall element with other values for vertical-align.
    相同的行为出现在将一个高元素与其他值对齐时,使用vertical-align

  • Even setting vertical-align to bottom (left) and top (right) moves the baseline. This is strange, since the baseline shouldn't be involved at all.
    即使将 vertical-align 设置为 bottom (左)和 top (右)也会移动基线。这很奇怪,因为基线根本不应该参与。

          
    <!-- left mark-up -->
    <span class="tall-box bottom"></span>
    <span class="short-box"></span>
    
    <!-- right mark-up -->
    <span class="tall-box top"></span>
    <span class="short-box"></span>
    
    <style type="text/css">
      .tall-box,
      .short-box { display: inline-block;
                   /* size, color, etc. */ }
    
      .bottom    { vertical-align: bottom; }
      .top       { vertical-align: top; }
    </style>

  • Placing two larger elements in a line and vertically aligning them moves the baseline where it fulfils both alignments. Then the height of the line box is adjusted (left). Adding a third element, that does not go beyond the line box's edges because of its alignment, affects neither the line box's height nor the baseline's position (middle). If it *does* go beyond the line box's edges, the line box's height and baseline are adjusted, again. In this case, our first two boxes are pushed down (right).
    将两个较大的元素排成一行并垂直对齐,会移动基线以满足这两者的对齐。接着,行框的高度会调整(左)。添加一个第三个元素,如果它不会超出行框的边缘,因为它的对齐方式,则不会影响行框的高度或基线的位置(中)。如果它确实超出了行框的边缘,行框的高度和基线又会被调整。在这种情况下,我们的前两个框会被压下(右)。

          
    <!-- left mark-up -->
    <span class="tall-box text-bottom"></span>
    <span class="tall-box text-top"></span>
    
    <!-- middle mark-up -->
    <span class="tall-box text-bottom"></span>
    <span class="tall-box text-top"></span>
    <span class="tall-box middle"></span>
    
    <!-- right mark-up -->
    <span class="tall-box text-bottom"></span>
    <span class="tall-box text-top"></span>
    <span class="tall-box text-100up"></span>
    
    <style type="text/css">
      .tall-box    { display: inline-block;
                     /* size, color, etc. */ }
    
      .middle      { vertical-align: middle; }
      .text-top    { vertical-align: text-top; }
      .text-bottom { vertical-align: text-bottom; }
      .text-100up  { vertical-align: 100%; }
    </style>

There Might Be a Little Gap Below Inline-Level Elements
行内级元素下方可能会有一点间隙

Have a look at this setting. It’s common if you try to vertical-align li elements of a list.
看看这个设置。如果你尝试垂直对齐 li 元素的列表,这是很常见的。

  
<ul>
  <li class="box"></li>
  <li class="box"></li>
  <li class="box"></li>
</ul>

<style type="text/css">
  .box { display: inline-block;
         /* size, color, etc. */ }
</style>

As you can see, the list items sit on the baseline. Below the baseline is some space to shelter the descenders of a text. This is causing the gap. The Solution? Just move the baseline out of the way, for example by aligning the list items with vertical-align: middle:
如您所见,列表项位于基线。基线下方有一些空间,用于容纳文本的下行部分。这造成了间隙。解决方案是什么?只需将基线移开,例如通过使列表项与 vertical-align: middle 对齐:

  
<ul>
  <li class="box middle"></li>
  <li class="box middle"></li>
  <li class="box middle"></li>
</ul>

<style type="text/css">
  .box    { display: inline-block;
            /* size, color, etc. */ }

  .middle { vertical-align: middle; }
</style>

This scenario does not occur for inline-blocks having text content, since content already moves the baseline up.
此场景不会发生在具有文本内容的内联块上,因为 内容已经将基线抬高

A Gap Between Inline-Level Elements Is Breaking the Layout
行内元素之间的间隙破坏了布局

This is mainly a problem of inline-level elements themselves. But since they are a requirement of vertical-align, it is good to know about this.
这主要是行内级元素本身的问题。但由于它们是垂直对齐的要求,了解这一点是很好的。

You can see this gap in the former example between the list items. The gap comes from the white-space between inline-elements present in your mark-up. All white-space between inline-elements is collapsed into one space. This space gets in the way, if we want to place two inline elements next to each other and giving them width: 50%, for example. There is not enough space for two 50%-elements and a space. So the line breaks into two lines destroying the layout (left). To remove the gap, we need to remove the white-space, for example with html comments (right).
在前面的例子中,您可以看到列表项之间的间隙。这个间隙来自于您的标记中内联元素之间的空白。所有内联元素之间的空白都会合并成一个空格。如果我们想把两个内联元素放在一起并给它们 width: 50%,那么这个空隙就会妨碍我们。例如,两个 50%的元素和一个空格的空间是不够的。因此,行会断裂成两行,破坏布局(左)。要消除间隙,我们需要去除空白,例如使用 html 注释(右)。

  
50% wide
50% wide... and in next line
50% wide
50% wide
<!-- left mark-up -->
<div class="half">50% wide</div>
<div class="half">50% wide... and in next line</div>

<!-- right mark-up -->
   <div class="half">50% wide</div><!--
--><div class="half">50% wide</div>

<style type="text/css">
  .half { display: inline-block;
          width: 50%; }
</style>

Vertical-Align Demystified
垂直对齐揭秘

Yea, that’s it. It is not very complicated once you know the rules. If vertical-align does not behave, just ask these questions:
是的,就这样。一旦你了解了规则,它并不复杂。如果vertical-align没有按预期工作,只需问这些问题:

  • Where is the baseline and top and bottom edge of the line box?
    线框的基线和上下边缘在哪里?
  • Where is the baseline and top and bottom edge of the inline-level elements?
    行内元素的基线、顶部和底部边缘在哪里?

This will corner the solution to the problem.
这将使问题的解决陷入困境。

Here is a more complex example how to vertically center an element in a <div> with vertical-align: middle.
这里是一个更复杂的示例 如何在 <div> 中垂直居中一个元素,使用 vertical-align: middle