vertical-align 用于定义内联元素的垂直对齐方式。
打开浏览器,我们可以看到 vertical- align 的全部属性值:
属性值大致可以分为以下 4 类:
- 基线对齐:baseline(默认值)、middle;
- 行框对齐:top、bottom;
- 内容区域对齐:text-top、text-bottom;
- 上下标签:sub、super。
基线对齐除了以上关键字属性值,vertical-align 也支持长度值和百分比值。
下面会依次介绍。
baseline:使内联元素的基线与其所在行盒子的基线对齐。
例子:
p { border: 2px #FF9800 solid; text-align: center; } span { background-color: #eee; padding: 5px 10px; margin-left: 5px; } span:first-child { font-size: 26px; } span:nth-child(2) { display: inline-block; height: 50px; } span:last-child { display: inline-block; height: 50px; } x Which wouldyou give
up?
middle:使内联元素的垂直中心位置与其所在行盒子基线高度的1/2处对齐。
例子:
div { border: 1px sandybrown solid; text-align: center; padding: 3px; } strong { background-color: silver; vertical-align: middle; } input { border: 1px #03A9F4 solid; vertical-align: middle; width: 70px; } xHello
行框对齐更多关于基线的介绍,可以参考:内联元素的两大基石之基线
top:使内联元素的顶部与其所在行盒子的上边框对齐。
bottom:使内联元素的底部与其所在行盒子的下边框对齐。
例子:
p { border: 2px #FF9800 solid; text-align: center; line-height: 80px; } span { display: inline-block; line-height: 1.5; background-color: #03A9F4; padding: 5px 10px; color: #fff; } span:first-child { vertical-align: top; } span:last-child { vertical-align: bottom; } xy
内容区域对齐例子中,我们可以看到,第一个 span 与最后一个 span 分别紧贴着行盒子的上下边框显示。
text-top:使内联元素的顶部与其行盒子内容区域(1)的上边缘对齐。
text-bottom:使内联元素的底部与其行盒子内容区域的下边缘对齐。
*(1)在开发者模式下,当鼠标放在元素上,可以大致显示内容区域的范围。
例子:
p { border: 2px #FF9800 solid; text-align: center; font-size: 60px; line-height: 150px; } span { display: inline-block; line-height: 1.5; background-color: #03A9F4; padding: 5px 10px; color: #fff; } span:first-child { vertical-align: text-top; } span:last-child { vertical-align: text-bottom; } Contentxy
例子中,我们可以看到,第一个 span 与最后一个 span 分别和内容区域上下边缘对齐。
有关于内容区域的范围,一直是比较模糊,因为它肉眼不可见。按照规范,它的高度应该是 1em,因此,内容区域大小会受到 font-family 和 font-size 的影响。这一点,在出现混排替换元素的时候尤其要注意,替换元素会撑起行盒子的高度,但不会改变内容区域的大小。
例子:
上下标签p { border: 2px #FF9800 solid; text-align: center; font-size: 60px; line-height: 150px; } span { display: inline-block; line-height: 1.5; background-color: #03A9F4; padding: 5px 10px; color: #fff; } span:first-of-type { vertical-align: text-top; } span:last-of-type { vertical-align: text-bottom; } canvas { width: 30px; height: 200px; background-color: chartreuse; } Contentxy
super 与 sub 分别表示下标和上标,在 html 中也有对应的标签,sup 与
sub。这两个属性值的作用比较单一,只能用来实现对垂直位置要求不高的上标下标效果。
例子:
长度值或百分比值h1 { text-align: center; background-color: thistle; } span, i { vertical-align: sub; font-size: 14px; } i { font-style: normal; vertical-align: super; } H2O@
vertical-align 取长度值或百分比值,都是相对于基线往上( 正值 )或往下( 负值 )偏移。
其中,百分比值是相对于 line-height 计算的。
例子:
vertical-align 与单元格div { border: 1px sandybrown solid; text-align: center; padding: 3px; } span { padding: 0 5px; } span:first-child { background-color: #FF9800; vertical-align: 20px; } span:last-child { background-color: #CDDC39; vertical-align: -20px; } x love you
vertical-align 属性也可以设置单元格( td 或 display 取值 table-cell 的元素 )中的内容的垂直对齐方式。
例子:
div { display: table; width: 100%; height: 120px; border: 2px slateblue solid; } span { display: table-cell; text-align: center; background-color: tan; border: 4px #fff solid; width: 25%; } span:first-of-type { vertical-align: baseline; border-right-width: 2px; } span:nth-of-type(2) { vertical-align: top; border-left-width: 2px; border-right-width: 2px; } span:nth-of-type(3) { vertical-align: middle; border-left-width: 2px; border-right-width: 2px; } span:last-of-type { vertical-align: bottom; border-left-width: 2px; } baseline top middle bottom
例子中,我们可以发现,在 table-cell 元素上设置 vertical-align 属性,但实际是在其子元素上发生作用。就算 table-cell 元素的子元素是一个块级元素,也一样可以设置其垂直对齐方式。
例子:
vertical-align 与 line-heightdiv { display: table; width: 100%; height: 120px; border: 2px slateblue solid; } span { display: table-cell; text-align: center; background-color: tan; border: 4px #fff solid; vertical-align: middle; } p { margin: 0; } middle
上面的内容中,简单介绍过 vertical-align 与 line-height 的关系,即 vertical-align 的百分比值是相对于 line-height 计算的。但它们的关系远远不止于此,甚至可以说,只要有内联元素,vertical-align 与 line-height 就一定同时出现,如果再加上" 透明文本节点 "的概念,那么很多内联元素排版的怪异表现,就都可以解释得通了。
怪异表现1:line-height 无效
首先,看一个正常的例子:
例子:
p { line-height: 30px; background-color: #9E9E9E; } span { background: #eee; } x-x-jquery
例子中,span 继承了 p 的 line-height 属性,因此行高为 30px,p 最终的高度也是 30px。
如果 span 中的字体变大,会发生什么呢?
例子:
p { line-height: 30px; background-color: #9E9E9E; } span { font-size: 20px; background: #eee; } x-x-jquery
显而易见,字体大小不同,影响了 p 的最终高度。
首先,p 上设置的 line-height 属性不但继承给了 span,也同样继承给了透明文本节点( span 前面的 x 便于观察此节点 ),此时,两者行高都是 30 px;
然后,内联元素默认 baseline 对齐,字体越大,基线越低,这就导致 span 发生向上移动;
最终,line-height 设置的 30px 无效。
知道了原因,那么优化方法也就变得简单了:让透明文本节点和 span 中字体一样大,修改 span 的 baseline 对齐为 top 对齐等等。
例子:
p { line-height: 30px; background-color: #9E9E9E; } span { font-size: 20px; vertical-align: top; background: #eee; } x-x-jquery
怪异表现2:替换元素下面的空白区域
如果块级元素的子元素为替换元素,那么块级元素的的高度值总会比替换元素的高度值大。
例子:
div { border: 1px sienna solid; } canvas { width: 80%; height: 50px; background-color: thistle; } x-
例子中,替换元素 canvas 的下边缘与 div 的下边框有一条很明显的空隙。
首先,内联元素默认 baseline 对齐,因此,透明文本节点( canvas 前面的 x 便于观察此节点 )的基线与 canvas 的基线( canvas 的下边缘 )对齐;
然后,内联元素默认的 line-height 取值 normal,通常为 1.3 左右,这就导致透明文本节点往下一定有半个行距;
最终,替换元素下面出现了空白的缝隙。
知道了原理,那么要清除这个间隙则变得容易:设定透明文本节点的 line-height 为 0( 或者 font-size 为 0 ),修改替换元素 baseline 对齐为 top、middle、 bottom 对齐等等。
例子:
div { line-height: 0; border: 1px sienna solid; } canvas { width: 80%; height: 50px; background-color: thistle; } x-
怪异表现3:margin 无效
例子:
div { border: 1px sienna solid; margin-top: 40px; } canvas { width: 80%; height: 50px; margin-top: -999px; background-color: thistle; } x-
例子中,替换元素 canvas 的 margin-top 设置为 -999px,但是 canvas 并不会继续向上移动。
实际上,原理和以上两种都类似,canvas 与透明文本节点为 baseline 对齐,而透明文本节点不可能跑到 div 外面,所以 canvas 也被限制在 div 里面。
总结
对于内联元素而言,会发生很多无法理解的现象,多去分析透明文本节点、vertical-align 与 line-height,有助于理解这些现象。
如有错误,欢迎指正,本人不胜感激。



