你所不知道的vertical-align
有些东西我们经常用,但是我们却并不了解它的原理,所以一旦换了场景,好多东西就不知道该怎么用了。最近一直很纠结 vertical-align 到底是怎么回事,因为不管是垂直对齐元素,还是消除inline-block的缝隙也好,我们总能用到它,可是就是不知道为什么。抱着刨根问底的态度,今天在网上发现了一篇好文章,无奈是英文,博主不是什么英语大神,看到英语也头疼,但奈何好文章都是英文。那就来吧,翻译一下午,虽然是撕心裂肺,但是感觉受益匪浅,文中有翻译不当的地方还请各位看官多多指正。
小二,上原文链接: Vertical-Align: All You Need To Know
我们经常需要在竖直方向上对齐一些并肩排列的元素。
CSS为我们提供了一些实现方法。有时候我会使用 float ,有时候也用 position:absolute ,有时候甚至利用手动添加内外边距的方法。
我并不喜欢这些方法。浮动只能对齐它们的顶部,而且需要手动清除浮动。绝对定位会使元素脱离文档流,以致于它们就不能影响周围的元素了。再说说使用固定的内外边距,会突然导致微弱的改变。
这里还有另一种值得信任的方法,那就是 vertical-align 。从专业角度讲,使用 vertical-align 来进行布局是一种“黑科技”,因为发明它并不是出于这个目的。 vertical-align 是为了对齐文本和紧邻文本的元素。尽管如此,你也能在不同场景下使用 vertical-align 去进行灵活细微的元素对齐工作,而且你并不需要知道元素的具体尺寸。
但是, vertical-align 有时候真的让人抓狂。它似乎有一些不可告人的秘密。例如,有时候你对一些元素设置 vertical-align ,你会发现它的对齐方式并没有改变,但是同一行的其它元素却变了。我时常哭晕在 vertical-align 的厕所中。
不幸的是,大部分关于它的资料都是浅显的。尤其是,如果你想找 vertical-align 关于布局方面的介绍时,他们大多告诉你错误的信息—— vertical-align 可以控制元素内部所有元素的竖直排列。他们总是给出最基础的场景应用,却从不介绍复杂的情况。
所以我给自己立下任务, 要一次弄清所有关于vertical-align的知识。 我看完 W3C的CSS说明 然后自己动手做了一些实验。结果就是这篇文章了。
那么,然我们一起来了解游戏规则吧。
vertical-align 用于对齐 行内级元素 。行内级元素的 display 属性是如下值中的一种:
inline元素 是包裹文本的基本标签。
inline-block元素 顾名思义是存在于inline中的block元素。它们可以设置宽高、内外边距、和边框。
inline级元素是一个挨着一个排在一行的元素。一旦一行放不下所有元素的时候,就会在下面创建一个新行。所有的行都有一个叫做 line-box 的东西,它是用来包裹这一行所有内容用的。line-box的高度是根据一行内所有内容的高度定的。如下图中所示:line-box的上下边沿用红线标出。(line-box的边沿平时是看不到的,画出来是为了方便读者理解)
理解垂直对齐最关键的一点在于理解相关元素的基线。还有一些场景中,元素的上下边沿也至关重要。现在就让我们看一下不同元素的基线和上下边沿到底在哪里?
行内元素的基线 是字符下面的一条线。具体是图中的蓝线。大约的说,基线是字体正中线下面的一条线。想具体了解的请看 W3C的详细说明
![Paste_Image.png]( http://upload-images.jianshu.io/upload_images/3068436-7140e215c7d96836.png ?
imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
我为line-box中的text-box(下面会讲到)加上了上下边沿(绿线)以及基线(蓝线)。我也为文字元素加上了背景色(灰色)。
line-box有一个上边沿,它和行内最高的元素的上边沿对齐;同样也有一个下边沿和行内最低元素的下边沿对齐。这两个边沿也就是图中的红线。
line-box的基线是会变化的 :
这可能是最令人困惑的部分。这就意味着,line-box的基线是会根据一定的规则动态改变的。
由于line-box的基线是不可见的,所以你也不可能准确的说出它到底在哪里。但是能通过一个简单方法知道它在哪。只要在一行内容的行首添加一个字符就行,例如:我加了一个"x"(行首灰色的那个)。如果这个字符没有进行任何人为方式的对齐,那么它的基线就默认是在line-box的基线上。
line-box的基线周围的空间,我们可以称之为 text box 。你可以把text box看做是一个在line-box中没有进行任何对齐的inline元素。它的高度等于父元素的字体大小。因此text box是用于包裹line box中没有设置任何对齐的文字的。图中绿线之间的部分就是text box。由于text box是和基线紧密相连的,因此它会随着基线的移动而移动。(在W3C说明中,text box叫做strut)
现在我们知道了所有的预备知识点,让我们做一下总结:
我们通过使用 vertical-align 可以把上面我们介绍的那些参考点(基线,上线边沿等)设置成确定的关系。
主要分一下两种情况:
![Paste_Image.png]( http://upload-images.jianshu.io/upload_images/3068436-e22cccdbf8b09e87.png ?
imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
以下的两种情况,其实也是相对于line-box的基线的一种对齐,因为text-box的上下边沿也是取决于基线的。
我们现在能够在具体的场景下更细致的研究vertical-align了。尤其是,我们将解决一些常见的问题。
长久以来一直困扰我的一个问题:我想让一个图标和它旁边的文字居中对齐时,仅仅对图标使用 vertical-align:middle 似乎并没有真正的使两者居中对齐。
来看看下面这个例子:
下图还是这个例子,不过我为其添加了一些标注帮助理解,这些线都是我们之前已经讲过的:
使用vertial-align是的一大缺陷就是:line-box的基线的位置受其内部所有元素的影响。我们假设这样一种情况,一个元素相对于line-box的基线对齐,那么当line-box的基线位置发生改变时,那么元素的位置也会跟着改变。
来看一些例子:
当我们为这个比较高的元素设置其它的 vertical-align 值时,也会有相同的表现。
看看下面的例子。通常都会有如下情况出现,当你想对齐竖直对齐li元素的时候。
正如你所看到的,li元素其实默认是和基线对齐的,基线下面是留有一部分空白的,这个空白是可以容纳半个“x”的空间。这就导致了空隙的存在。如何解决?我们可以改变基线的位置,例如给li元素设置对齐方式为 vertical-align: middle
这种情况不会发生在包含文本内容的inline-block元素身上,因为 文本内容已经把基线的位置抬高了 。
这个问题主要还是inline级元素自身问题造成的。但是鉴于这种情况也影响了竖直对齐,我们还是了解一下比较好。
和上个例子一样,这个例子也是由空隙造成的。这个空隙主要来自于inline元素之间的空格符。inline元素之间的所有空格符会合并为一个空格。如果你想让两个inline元素并排显示,并且 width:50% ,那么这个空格就是个绊脚石。一行的空间不足以容纳两个 width:50% 和一个空格。所以右边的元素就被挤下去了。要想消除缝隙,你就得消除空格。
就是这样。一旦你知道了规则之后它看起来就不那么复杂了。如果下次 vertical-align 再不听话了,就问如下的两个问题:
我相信问题马上就会得到解答。
至此结束,不知道有几个人能耐心的看完……