基本概念
vertical-align 用于定义内联元素的垂直对齐方式。
打开浏览器,我们可以看到 vertical- align 的全部属性值:
属性值大致可以分为以下 4 类:
- 基线对齐:baseline(默认值)、middle;
- 行框对齐:top、bottom;
- 内容区域对齐:text-top、text-bottom;
- 上下标签: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,有助于理解这些现象。
如有错误,欢迎指正,本人不胜感激。