欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

Vertical-Align: 你需要知道的所有事【译】_html/css_WEB-ITnose

程序员文章站 2022-05-19 19:57:52
...

Vertical-Align: 你需要知道的所有事

原文地址: Vertical-Align: All You Need To Know

我经常需要垂直对齐元素。

CSS提供了一些可能的方法。有时我用 float 解决它,或使用 position: absolute; ,还有时甚至要恶心地手动添加 margin 和 padding 。

我不是真的喜欢这些解决方案。 float 只能对准在其顶部而且需要手动清除。绝对定位将元素从文档流中抽离出来,这样它们就不再能撑开(影响)其包含块。使用固定的 margin 和 padding 则很容易被微小的变化所破坏。

但这里有另一个方法: vertical-align ,我认为它值得得到更多的信赖。从技术上讲,使用 vertical-align 布局是一种hack方式,因为它不是为这个原因发明的。它的存在是为了对齐文本和文本旁的元素。尽管如此,你也可以在不同的上下文中使用 vertical-align 来非常灵活和精准地对齐元素。优点是元素的大小不需要知道,且留在文档流中,所以其他元素(包含块)可以响应布局尺寸的改变,这使它成为一个有价值的选择。

vertical-align的独特性

但是, vertical-align 有时会相当卑鄙,并使你感到沮丧。在工作中似乎有一些神秘的规则,例如,这种情况经常发生,被改变了 vertical-align 的元素并没有改变它的对齐方式,但同一行的其他元素却改变了!我有时仍然被 vertical-align 拖到黑暗的角落并撕扯头发。

不幸的是,大部分关于这个的教程都有点浅,特别是如果我们要使用 vertical-align 来布局。大多数人专注于尝试垂直对齐元素的一些误解,他们给出基本的介绍,并解释在非常简单的情况下如何对齐元素,但没有解释棘手的部分。

所以,我给自己定了个目标: 彻底弄清楚 vertical-align 的行为 ,不留下历史问题。我最终通过W3C的 CSS 规范 和试验一些例子得到了结果——这篇文章。

使用vertical-align的要求

vertical-align 用来调整 inline 级元素。这些元素的 display 属性为:

  • inline
  • inline-block
  • inline-table(本文不涉及)

inline元素基本上是文本的包裹标签。

inline-block元素正如它们的名字:住在行内的块元素。他们可以有一个width和height(也可能由它内部内容撑开),以及padding、border和margin。

inline元素逐个从左到右地被放置在一行内。一旦有更多的元素加入,使当前行无法放下,一个新的行就会在下方产生。所有这些行有所谓的 line box ,其中包含所有的内容。不同尺寸的内容意味着不同高度的line box。在下图中,line box的顶部和底部是红色线表示的:

line box描绘出了我正在试验的区域。在这些line box中,属性 vertical-align 是负责调整单个元素的。 所以,元素对齐跟什么相关?

关于baseline和外边缘

垂直对齐最重要的关注点是要对其元素的baseline。在某些情况下,元素的包围盒的顶部和底部的边缘也变得很重要。让我们来看看每种类型的元素baseline和外边缘在哪里:

inline元素

在这里你看到三行的文本相邻排布。行高的顶部和底部是由红线表示的,字体的高度是由绿线来表示的,而baseline是由蓝线表示的。在左边,文本具有一个与字体大小相同的行高,绿色和红线在上下都重叠了。在中间,行高(line-height)是字体大小的两倍大。在右边,行高是字体大小(font-size)的一半。

inline元素的外边缘跟自己line-height的顶部和底部边缘对齐,如果line-height小于font-size的话也不会改变。所以,在上面的图中的行的外边界是红线。

inline元素的baseline字符底部所坐的线,就是图中的蓝线。粗略地说,baseline是在font-size中间下面的一个地方,看看W3C规范的 详细定义 。

inline-block元素

从左到右,你看到的是一个拥有 流 内容(一个“c”)的inline-block元素,一个拥有流内容且 overflow: hidden; 的inline-block元素和一个没有流内容的inline-block元素(但内容区域有一个高度)。margin的边界由红线表示,以及黄色的border,绿色的padding和蓝色的内容区域,蓝线是每个inline-block元素的baseline。

inline-block元素的外边缘是其 margin-box 的顶部和底部边缘,即图中的红线。

inline-block的baseline取决于元素是否具有流内容:

  • 在流内容的情况下,inline-block元素的baseline是正常流的最后一个内容元素的baseline(左边的例子)。对于这最后一个元素,它的baseline位置由它自己的规则决定。
  • 在流内容,但具有overflow:hidden的情况下,baseline是margin-box的底边缘(中间的例子),也相当于inline-block元素的底边缘。
  • 如果没有流内容,则跟上一个一样,baseline位于margin-box的底边缘(右边的例子)。

line box

你已经看过了这张图上面的设置,这一次,我画出了line box的text box的顶部和底部边缘(绿线,下文也是)以及baseline(蓝线)。我还给该区域的文本元素添加了一个灰色的背景来强调他们。

该line box具有一个与该行最顶的元素的顶部边缘对齐的 顶部边缘 和一个与该行最底的元素的底部边缘对齐的 底部边缘 ,即是上面图中的红色线所表示的盒子。

line box的baseline是可变的:

CSS 2.1并没有定义line box的baseline. —- W3C规范

这可能是使用vertical-align时最令人困惑的部分。意思是,baseline的位置要在满足所有其他条件,如vertical-align设置和最小化line box的高度的前提下来决定,是方程中的一个*参数。

由于line box的baseline是不可见的,无法直观感知。但是,你可以很容易地让它变得可见。通过在行的开头加一个字符,比如上图中的字母“×”。如果这个字符没有以任何方式进行对齐,则默认情况下其底部将坐在baseline上。

在其baseline的基础上,line box有一个称为 text box 的东西。该text box可以简单地被认为是line box中一个没有任何对齐的inlne元素。它的高度等于它的父元素的font-size。因此,text box只包裹住line box中的无格式文本,由上图中的绿线表示。因为这个text box位置基于baseline,所以它会随baseline移动。(注:此text box在W3C规范中称为 strut )

唉,这是最难的部分。现在,我们拥有了分析原理的所有前提条件,让我们迅速总结最重要的事实:

  • 有一个区域称为 line box ,这是要对齐的区域。它有一个 baseline ,一个 text box 和一个 顶部 和 底部边缘 。
  • 有 inline级元素 。这些是要被对齐的对象。他们有一个 baseline 和一个 顶部 和 底部边缘 。

vertical-align的取值

从上面的列表总结出来的使用 vertical-align 的要点中,我设置了几种关系样例。

将元素的baseline与line box的baseline对齐

  • baseline:该元素的baseline恰好与line box的baseline重合。
  • sub:该元素的baseline偏移到line box的baseline下方。
  • super:该元素的baseline偏移到line box的baseline上方。
  • :该元素的baseline以line-height高度乘以百分比的距离相对于line box的baseline偏移。
  • :该元素的baseline以绝对长度相对于line box的baseline偏移。

将元素的外边缘与line box的baseline对齐

  • middle:元素的顶部和底部边缘的中点与line box的baseline加上1/2小写字母x高度的位置对齐。

将元素的外边缘与line box的text box对齐

这2种情况也可以以相对于line box的baseline对齐的方式展现出来,因为text box的位置是由baseline确定的。

  • text-top:该元素的顶部边缘与line box的text box顶部边缘对齐。
  • text-bottom:该元素的底部边缘与line box的text box的底部边缘对齐。

将元素的外边缘与line box的外边缘对齐

  • top:元素的顶部边缘与line box的顶部边缘对齐。
  • bottom:该元素的底部边缘与line box的底部边缘对齐。

正式的定义 可以在W3C规范中找到。

为什么vertical-align以这种规则表现

我们现在可以在特定情况下来研究一下垂直对齐,特别是有可能会出错的情况。

居中一个图标

下面这个问题曾经烦扰了我:我想把图标与旁边的一行文本垂直居中对齐,只是给图标设置 vertical-align: middle; 似乎并没有如设想的一样居中。看看底下这个例子: