vertical-align适用于inline-level元素,即inline,inline-block或inline-table 。css
inline元素的外边缘是由它的line-height决定的。
红线:元素外边缘,即行高的顶部和底部边缘
。html
绿线:字体的高度。web
蓝线:基线。segmentfault
上图中,左侧的那个,文本的行高设置为与字体大小相同的高度。上下两边绿色和红色的线均重合为一条线。中间的那个,行高是字体高的两倍。右边的那个,行高是字体高的一半。字体
inline-block元素的外边缘就是它的margin-box的顶部和底部边缘。
红线:元素外边缘,即margin-box的顶部和底部边缘
。spa
蓝线:基线。3d
上图中从左到右能够看到:一个inline-block元素里面有in-flow内容(一个“C”),一个inline-block元素有in-flow内容和overflow: hidden,一个inline-block元素没有in-flow内容(可是内容区域有高度)。code
Inline-block元素的基线取决于元素是否具备in-flow内容:orm
有in-flow内容,inline-block元素的基线是普通流中最后一个内容元素的基线(例如左边那个)。对于最后一个元素,它的基线是根据它本身的规则肯定位置的。htm
有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:在非替换元素中,指元素中每一个字符的字体大小串在一块儿所组成的框;在替换元素中,元素的固有高度加上任何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基线的方法:在行的开头增长一个字符,就像上图中增长的“X”。它默认地坐在基线上。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值为百分比时,是有影响的。
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的底部边缘对齐。
例如:
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,所以能够看到红框降低,父元素变高了。
<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元素内添加内容。由于内容会将基线上移。