1、vertical-align属性值分为以下4类:
线类,如baseline(默认值)、top、middle、bottom;
文本类,如text-top、text-bottom;
上标下标类,如sub、super;
数值百分比类,如20px、2em、20%等。
数值百分比类根据计算值的不同,相对于基线往上或往下偏移,到底是往上还是往下取决于vertical- align的计算值是正值还是负值,如果是负值,往下偏移,如果是正值,往上偏移。
vertical-align的默认值是baseline,即基线对齐,而基线的定义是字母x的下边缘。因此,内联元素默认都是沿着字母x的下边缘对齐的。对于图片等替换元素,往往使用元素本身的下边缘作为基线。如图所示:
负值全部都是往下偏移,正值全部都是往上偏移,而且数值大小全部都是相对于基线位置计算的,因此,从这一点来看,vertical-align:baseline等同于vertical-align:0。
在CSS世界中,凡是百分比值,均是需要一个相对计算的值,例如,margin和padding是相对于宽度计算的,line-height是相对于font-size计算的,而这里的vertical- align属性的百分比值则是相对于line-height的计算值计算.
2、vertical-align起作用的前提条件就是:只能应用于内联元素以及display值为table-cell的元素。浮动和绝对定位会让元素块状化。
有时会觉得vertical-align在内联元素下也不能生效
.box {
height: 128px;
}
.box > img {
height: 96px;
vertical-align: middle;
}
"box">
"1.jpg">
这种情况看上去是vertical-align:middle没起作用,实际上,vertical-align是在努力地渲染的,只是行框盒子前面的“幽灵空白节点”高度太小,如果我们通过设置一个足够大的行高让“幽灵空白节点”高度足够,就会看到vertical-align:middle起作用了,代码如下所示:
.box {
height: 128px;
line-height: 128px;
/* 关键CSS属性,使得幽灵空白节点填充行间距,高度变高 */
}
.box > img {
height: 96px;
vertical-align: middle;
}
看一段代码,发现vertical-align无法作用到table-cell的元素上
.cell {
height: 128px;
display: table-cell; }
.cell > img {
height: 96px;
vertical-align: middle;
}
"cell">
"1.jpg">
结果图片并没有要垂直居中的迹象,还是紧贴着父元素的上边缘.
但是,如果vertical-align:middle是设置在table-cell元素上,CSS代码如下:
.cell {
height: 128px;
display: table-cell;
vertical-align: middle;
}
.cell > img { height: 96px; }
虽然就效果而言,table-cell元素设置vertical-align垂直对齐的是子元素,但是其作用的并不是子元素,而是table-cell元素自身。就算table-cell元素的子元素是一个块级元素,也一样可以让其有各种垂直对齐表现。
3、vertical-align和line-height之间的关系
.box {
line-height: 32px;
}
.box > span {
font-size: 24px;
}
"box">
文字
看以上代码,容器高度和行高不一致。其中有一个很关键的点,那就是24px的font-size大小是设置在元素上的,这就导致了外部
<div class="box">
x<span>文字xspan>
div>
此时,我们可以明显看到两处大小完全不同的文字。一处是字母x构成了一个“匿名内联盒子”,另一处是“文字 x”所在的元素,构成了一个“内联盒子”。由于都受line- height:32px影响,因此,这两个“内联盒子”的高度都是32px。下面关键的来了,对字符而言,font-size越大字符的基线位置越往下,因为文字默认全部都是基线对齐,所以当字号大小不一样的两个文字在一起的时候,彼此就会发生上下位移,如果位移距离足够大,就会超过行高的限制,而导致出现意料之外的高度
上图非常直观地说明了为何最后容器的高度会是36px,而非line-height设置的32px。
解决方案:
我们可以让“幽灵空白节点”和后面元素字号一样大,也就是
.box {
line-height: 32px;
font-size: 24px;
} .box > span {}
或者改变垂直对齐方式,如顶部对齐,这样就不会有参差位移了
.box {
line-height: 32px; }
.box > span {
font-size: 24px;
vertical-align: top; }
现象:任意一个块级元素,里面若有图片,则块级元素高度基本上都要比图片的高度高,如下代码,结果.box元素的高度可能就会像下图一样,底部平白无故多了5像素
.box {
width: 280px;
outline: 1px solid #aaa;
text-align: center;
}
.box > img { height: 96px; }
"box"> "1.jpg">
间隙产生的三大元凶就是“幽灵空白节点”、line-height和vertical-align属性。为了直观演示原理,我们可以在图片前面辅助一个字符x代替“幽灵空白节点”,并想办法通过背景色显示其行高范围如下图示:
当前line-height计算值是20px,而font-size只有14px,因此,字母x往下一定有至少3px的半行间距(具体大小与字体有关),而图片作为替换元素其基线是自身的下边缘。根据定义,默认和基线(也就是这里字母x的下边缘)对齐,字母x往下的行高产生的多余的间隙就嫁祸到图片下面,让人以为是图片产生的间隙,实际上,是“幽灵空白节点”、line-height和vertical-align属性共同作用的结果。
清除该间隙的方法:
(1)图片块状化。可以一口气干掉“幽灵空白节点”、line-height和vertical- align。
(2)容器line-height足够小。只要半行间距小到字母x的下边缘位置或者再往上,自然就没有了撑开底部间隙高度空间了。比方说,容器设置line-height:0。
(3)容器font-size足够小。此方法要想生效,需要容器的line-height属性值和当前font-size相关,如line-height:1.5或者line-height:150%之类;否则只会让下面的间隙变得更大,因为基线位置因字符x变小而往上升了。
(4)图片设置其他vertical-align属性值。间隙的产生原因之一就是基线对齐,所以我们设置vertical-align的值为top、middle、bottom中的任意一个都是可以的
前面提到的一个问题
.box > img { height: 96px;
margin-top: -200px; }
按照理解,-200px远远超过图片的高度,图片应该完全跑到容器的外面,但是,图片依然有部分在.box元素中,而且就算margin-top设置成-99999px,图片也不会继续往上移动,完全失效。其原理和上面图片底部留有间隙实际上是一样的,图片的前面有个“幽灵空白节点”,而在CSS世界中,非主动触发位移的内联元素是不可能跑到计算容器外面的,导致图片的位置被“幽灵空白节点”的vertical-align:baseline给限死了。我们不妨把看不见的“幽灵空白节点”使用字符x代替
因为字符x下边缘和图片下边缘对齐,字符x非主动定位,不可能跑到容器外面,所以图片就被限死在此问题,margin-top失效。
.box {
text-align: justify;
}
.justify-fix {
display: inline-block;
width: 96px; }
<div class="box">
<img src="1.jpg" width="96">
<img src="1.jpg" width="96">
<img src="1.jpg" width="96">
<img src="1.jpg" width="96">
<i class="justify-fix">i>
<i class="justify-fix">i>
<i class="justify-fix">i>
div>
按照之前解决问题的方法,我们可以直接给.box元素来个line-height:0解决垂直间隙问题,结果,这样设置之后的效果却如下图示。图片和图片之间的间隙是没有了,但是图片和最后的占位元素之间依然有几像素的间距。这个与inline-block和baseline有关,后面章节解惑