一、适用元素
vertical-align适用于inline-level元素,即inline,inline-block或inline-table 。
二、inline与inline-block元素的外边缘和基线
inline元素的外边缘和基线
inline元素的外边缘是由它的line-height决定的。
红线:元素外边缘,
即行高的顶部和底部边缘
。绿线:字体的高度。
蓝线:基线。
上图中,左侧的那个,文本的行高设置为与字体大小相同的高度。上下两边绿色和红色的线均重合为一条线。中间的那个,行高是字体高的两倍。右边的那个,行高是字体高的一半。
inline-block元素的外边缘和基线
inline-block元素的外边缘就是它的margin-box的顶部和底部边缘。
红线:元素外边缘,
即margin-box的顶部和底部边缘
。蓝线:基线。
上图中从左到右可以看到:一个inline-block元素里面有in-flow内容(一个“C”),一个inline-block元素有in-flow内容和overflow: hidden,一个inline-block元素没有in-flow内容(但是内容区域有高度)。
Inline-block元素的基线取决于元素是否具有in-flow内容:
有in-flow内容,inline-block元素的基线是普通流中最后一个内容元素的基线(例如左边那个)。对于最后一个元素,它的基线是根据它自己的规则确定位置的。
有in-flow内容并且使用了值不是visible的overflow,基线就在margin-box的底部边缘那个位置(例如中间那个)。因此,它与inline-block元素的底部边缘一样。
没有in-flow内容,基线也是在margin-box的底部边缘那个位置(例如右边那个)。
例如:下图中紫色为基线,两个span均是基线对齐。两幅图对比可以看出,随着第一个span元素中内容的增多,基线下移了。
<style type="text/css">
.box {
display: inline-block;
width: 100px;
height: 50px;
border: 1px solid red;
}
</style>
<div>
<span class="box">士大夫和健康</span>
<span class="box"></span>
</div>
<style type="text/css">
.box {
display: inline-block;
width: 100px;
height: 50px;
border: 1px solid red;
}
</style>
<div>
<span class="box">士大夫和健康士大夫和健康</span>
<span class="box"></span>
</div>
【注】:如果一个元素是浮动的(float:left/right),绝对定位的(position:absolute/fixed)或者是根元素(html),那么它被称之为流外的元素(out-of-flow)。如果一个元素不是流外的元素,那么它被称之为流内的元素(in-flow)。
三、content-area、inline box和line box
content-area:在非替换元素中,指元素中每个字符的字体大小串在一起所组成的框;在替换元素中,元素的固有高度加上任何margins, borders或padding。
inline box:每个元素的content-area加上leading。对于非替换元素,元素的inline box的高度等于line-height的值;对于替换元素,元素的inline box的高度等于该元素的固有高度加上任何margins, borders或 padding。
line box:一行就是一个line box。line box的边界是该行内inline boxes的最高点和最低点,即line box的顶部边缘是该行内最高inline box的顶部边缘,底部边缘是该行内最底inline box的底部边缘。
line box的文本盒和基线
文本盒可以当做是放在line box里面的没有任何对齐的行内元素。文本盒的高度等于它的父元素的字体大小。
因此,文本盒只是把line box的无格式文本围起来了。这个盒子就是下图中用绿线标出来的那个。因为这个文本盒与基线相关联,当基线移动时,它也移动。
line box的基线无法定义。line box的基线被放在能够实现所有条件的地方。
绿色:line box的文本盒。
红色:line box的顶部和底部边缘。
蓝色:基线。
灰色:文本元素的区域。
查看line box基线的方法:在行的开头增加一个字符,就像上图中增加的“X”。它默认地坐在基线上。line box是垂直对齐发生的区域。line box有一条基线,一个文本盒和一个顶部和底部边缘。
line box高如何计算
当一行中仅有
行内
不可替换元素,且这些元素都是相同的 font-size、line-height和vertical-align。则content-area=font-size, line-box的高=line-height。
当一行中包含
行内元素
,这些元素包括可替换和不可替换,这些元素有不同的 font-size和 line-height。则按以下方式计算:content-area的高由每个不可替换元素的font-size,以及替换元素的固有高度和任何padding, borders,或margins决定。leading应用于每一个元素,一半放在顶部,一半放在底部。line box的顶部边缘是该行内最高inline box的顶部边缘,底部边缘是该行内最底inline box的底部边缘。
例如:
<P style="line-height: 12pt; font-size: 12pt;">
<A style="font-size: 128pt;">anchor</A> angry text
<B style="vertical-align: top">bold</B>
</P>
anchor的content-area是128pt,但是他的inline box是12pt。假设字体是Helvetica,那么
descent : 128pt*219/1000=28pt
ascent : 128pt*781/1000=100pt
halfleading : (12pt-128pt)/2 = -58pt
inline box的top:100pt-58pt=42pt
inline box的bottom:58pt-28pt=30pt
所以这个inline box的top为基线上42pt,bottom为基线上30pt。同理可得匿名文本angry text的top是基线上10pt,基线下2pt。所以line-box的高是44pt:基线上42pt,基线下2pt。
将angry text文本去掉,会发现父元素P高度不变。
原因:根据W3C规范:
在由inline-level元素组成的块容器元素中,line-height确定了该元素内部line boxes的最小高度。这个最小高度由基线上的最小高度和基线下的最小深度组成,就像每个line box都是由宽度为零,拥有父元素的font-size和line-height的inline box(假想元素)开始的。
我的理解是line box是在这个假想元素的基础上往两边延伸。例如:
<P style="line-height: 44pt; font-size: 12pt;">
<A style="font-size: 128pt;">anchor</A>
</P>
p元素中只有anchor文本,但是该文本的inline box的top为基线上42pt,bottom为基线上30pt。所以line box的top为基线上42pt,而line box的bottom不是基线上的30pt,而是原先假想元素的基线下的最小深度(即上图中蓝线到最后一条红线的距离)。
因此,即使没有angry text文本,基线下也会有一个最小深度,所以导致P元素的高度不变。
注:
例子中计算Helvetica字体用的219和781是修改过的数据,只是为了让数据好看点,实际应该是接近于225和775。
leading = line-height - font-size。
其中一半leading加到文字上方,另一半leading加到文字下方。line-height对可替换元素的inline box没有影响,但是当该元素的vertical-align值为百分比时,是有影响的。
四、Vertical-Align的值
baseline:元素的基线在line box的基线顶部。
sub:元素的基线移动到line box基线以下。
<percentage>:元素的基线通过与line-height相关联的percentage ,相对于line box的基线进行偏移。
<length>:元素的基线通过绝对长度相对于line box的基线进行偏移。
middle:元素顶部和底部两者间的中点与line box的基线加上二分之一的x-height对齐。
text-top:元素的顶部边缘与line box的文本盒的顶部边缘对齐。
text-bottom:元素的底部边缘与line box的文本盒的底部边缘对齐。
top: 元素的顶部边缘与line box的顶部边缘对齐。
bottom:元素的底部边缘与line box的底部边缘对齐。
五、Vertical-Align的诡异行径
Line Box的基线的移动
例如:
div {
font-size: 16px;
line-height: 1;
background-color: #eee;
margin-top: 10px;
}
.tall-box {
border: 1px solid red;
width: 40px;
height: 40px;
display: inline-block;
}
.short-box {
border: 1px solid black;
width: 40px;
height: 10px;
display: inline-block;
}
<div>
<span class="tall-box" style="vertical-align: text-top;"> </span>
<span>Exg</span>
<span class="short-box"></span>
</div>
若将tall-box的vertical-align变成top,得下图
从上下两幅图对比可以看出,随着vertical-align从text-top变成top,Exg往上移,导致字体高超出了父div的边界。这是由于line-height的高小于字体高。
若将第一个图中的父div的line-height变为2,使Exg的line-height值大于字体原本的高度,则得下图。从图中可以看到,红框下降了,父div的高度变高了。这是由于红框是text-top对齐,由此可知道基线位置在哪里。而基线位置的确定可以确定Exg和黑框的位置。而line box的顶部边缘是该行内最高元素的顶部边缘,这时候最高的是Exg,因此可以看到红框下降,父元素变高了。
Inline-Level元素的底下间隙
<ul>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
</ul>
<style type="text/css">
.box{
display: inline-block;
}
</style>
可以看到li元素底下有间隙。
间隙产生的原因:因为列表项位于基线上,而在基线下是放文本descenders空间。
取消该间隙的方法:
设置li元素vertical-align: middle;
在li元素内添加内容。因为内容会将基线上移。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。