为了账号安全,请及时绑定邮箱和手机立即绑定

内联元素的两大基石之 vertical-align

基本概念

vertical-align 用于定义内联元素的垂直对齐方式。
打开浏览器,我们可以看到 vertical- align 的全部属性值:

图片描述

属性值大致可以分为以下 4 类:

  1. 基线对齐:baseline(默认值)、middle;
  2. 行框对齐:top、bottom;
  3. 内容区域对齐:text-top、text-bottom;
  4. 上下标签:sub、super。

除了以上关键字属性值,vertical-align 也支持长度值和百分比值。
下面会依次介绍。

基线对齐

baseline:使内联元素的基线与其所在行盒子的基线对齐。

例子:

<style>
    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;
    }
</style>

<p>
    x Which <span>would</span><span>you give <br>up?</span><span></span>
</p>

图片描述

middle:使内联元素的垂直中心位置与其所在行盒子基线高度的1/2处对齐。

例子:

<style>
    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;
    }
</style>

<div>
    x<strong>Hello</strong><input type="text" value="world">
</div>

图片描述

更多关于基线的介绍,可以参考:内联元素的两大基石之基线

行框对齐

top:使内联元素的顶部与其所在行盒子的上边框对齐。
bottom:使内联元素的底部与其所在行盒子的下边框对齐。

例子:

<style>
    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;
    }
</style>

<p>
    <span>x</span><span>y</span>
</p>

图片描述

例子中,我们可以看到,第一个 span 与最后一个 span 分别紧贴着行盒子的上下边框显示。

内容区域对齐

text-top:使内联元素的顶部与其行盒子内容区域(1)的上边缘对齐。
text-bottom:使内联元素的底部与其行盒子内容区域的下边缘对齐。

*(1)在开发者模式下,当鼠标放在元素上,可以大致显示内容区域的范围。

例子:

<style>
    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;
    }
</style>

<p>
    Content<span>x</span><span>y</span>
</p>

图片描述

例子中,我们可以看到,第一个 span 与最后一个 span 分别和内容区域上下边缘对齐。
有关于内容区域的范围,一直是比较模糊,因为它肉眼不可见。按照规范,它的高度应该是 1em,因此,内容区域大小会受到 font-family 和 font-size 的影响。这一点,在出现混排替换元素的时候尤其要注意,替换元素会撑起行盒子的高度,但不会改变内容区域的大小。

例子:

<style>
    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;
    }
</style>

<p>
    Content<canvas></canvas><span>x</span><span>y</span>
</p>

图片描述

上下标签

super 与 sub 分别表示下标和上标,在 html 中也有对应的标签,sup 与
sub。这两个属性值的作用比较单一,只能用来实现对垂直位置要求不高的上标下标效果。

例子:

<style>
    h1 {
        text-align: center;
        background-color: thistle;
    }
    
    span,
    i {
        vertical-align: sub;
        font-size: 14px;
    }
    
    i {
        font-style: normal;
        vertical-align: super;
    }
</style>

<h1>
    H<span>2</span>O<i>@</i>
</h1>

图片描述

长度值或百分比值

vertical-align 取长度值或百分比值,都是相对于基线往上( 正值 )或往下( 负值 )偏移。
其中,百分比值是相对于 line-height 计算的。

例子:

<style>
    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;
    }
</style>

<div>
    x
    <span>love</span>
    <span>you</span>
</div>

图片描述

vertical-align 与单元格

vertical-align 属性也可以设置单元格( td 或 display 取值 table-cell 的元素 )中的内容的垂直对齐方式。

例子:

<style>
    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%;
    }

    /* sub、super、text-top、text-bottom 效果与 baseline 相同 */ 
    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;
    }
</style>

<div>
    <span>baseline</span>
    <span>top</span>
    <span>middle</span>
    <span>bottom</span>
</div>

图片描述

例子中,我们可以发现,在 table-cell 元素上设置 vertical-align 属性,但实际是在其子元素上发生作用。就算 table-cell 元素的子元素是一个块级元素,也一样可以设置其垂直对齐方式。

例子:

<style>
    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;
        vertical-align: middle;
    }
    
    p {
        margin: 0;
    }
</style>

<div>
    <span><p>middle</p></span>
</div>

图片描述

vertical-align 与 line-height

上面的内容中,简单介绍过 vertical-align 与 line-height 的关系,即 vertical-align 的百分比值是相对于 line-height 计算的。但它们的关系远远不止于此,甚至可以说,只要有内联元素,vertical-align 与 line-height 就一定同时出现,如果再加上" 透明文本节点 "的概念,那么很多内联元素排版的怪异表现,就都可以解释得通了。

怪异表现1:line-height 无效

首先,看一个正常的例子:

例子:

<style>
    p {
        line-height: 30px;
        background-color: #9E9E9E;
    }
    
    span {
        background: #eee;
    }
</style>

<p>
    x-<span>x-jquery</span>
</p>

图片描述

例子中,span 继承了 p 的 line-height 属性,因此行高为 30px,p 最终的高度也是 30px。
如果 span 中的字体变大,会发生什么呢?

例子:

<style>
    p {
        line-height: 30px;
        background-color: #9E9E9E;
    }
    
    span {
        font-size: 20px;
        background: #eee;
    }
</style>

<p>
    x-<span>x-jquery</span>
</p>

图片描述

显而易见,字体大小不同,影响了 p 的最终高度。
首先,p 上设置的 line-height 属性不但继承给了 span,也同样继承给了透明文本节点( span 前面的 x 便于观察此节点 ),此时,两者行高都是 30 px;
然后,内联元素默认 baseline 对齐,字体越大,基线越低,这就导致 span 发生向上移动;
最终,line-height 设置的 30px 无效。

图片描述

知道了原因,那么优化方法也就变得简单了:让透明文本节点和 span 中字体一样大,修改 span 的 baseline 对齐为 top 对齐等等。

例子:

<style>
    p {
        line-height: 30px;
        background-color: #9E9E9E;
    }
    
    span {
        font-size: 20px;
        vertical-align: top;
        background: #eee;
    }
</style>

<p>
    x-<span>x-jquery</span>
</p>

图片描述

怪异表现2:替换元素下面的空白区域

如果块级元素的子元素为替换元素,那么块级元素的的高度值总会比替换元素的高度值大。

例子:

<style>
    div {
        border: 1px sienna solid;
    }
    
    canvas {
        width: 80%;
        height: 50px;
        background-color: thistle;
    }
</style>

<div>
    x-<canvas></canvas>
</div>

图片描述

例子中,替换元素 canvas 的下边缘与 div 的下边框有一条很明显的空隙。
首先,内联元素默认 baseline 对齐,因此,透明文本节点( canvas 前面的 x 便于观察此节点 )的基线与 canvas 的基线( canvas 的下边缘 )对齐;
然后,内联元素默认的 line-height 取值 normal,通常为 1.3 左右,这就导致透明文本节点往下一定有半个行距;
最终,替换元素下面出现了空白的缝隙。

图片描述

知道了原理,那么要清除这个间隙则变得容易:设定透明文本节点的 line-height 为 0( 或者 font-size 为 0 ),修改替换元素 baseline 对齐为 top、middle、 bottom 对齐等等。

例子:

<style>
    div {
        line-height: 0;
        border: 1px sienna solid;
    }
    
    canvas {
        width: 80%;
        height: 50px;
        background-color: thistle;
    }
</style>

<div>
    x-<canvas></canvas>
</div>

图片描述

怪异表现3:margin 无效

例子:

<style>
    div {
        border: 1px sienna solid;
        margin-top: 40px;
    }
    
    canvas {
        width: 80%;
        height: 50px;
        margin-top: -999px;
        background-color: thistle;
    }
</style>

<div>
    x-<canvas></canvas>
</div>

图片描述

例子中,替换元素 canvas 的 margin-top 设置为 -999px,但是 canvas 并不会继续向上移动。
实际上,原理和以上两种都类似,canvas 与透明文本节点为 baseline 对齐,而透明文本节点不可能跑到 div 外面,所以 canvas 也被限制在 div 里面。

总结

对于内联元素而言,会发生很多无法理解的现象,多去分析透明文本节点、vertical-align 与 line-height,有助于理解这些现象。


如有错误,欢迎指正,本人不胜感激。

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
1.4万
获赞与收藏
860

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消