Closed Adamwu1992 closed 5 years ago
所谓行盒子,就是在block元素中,如果存在inline元素,这些inline元素按照顺序排列,宽度不够时会自动换到下一行,每一行就形成了一个inline box。
每一个inline box的高度是由它包含的子元素决定的,直觉上inline box的高度等于最高子元素的高度,但是这是不对的,inlne box的高度还和子元素的对齐方式有关。
<style> .inner { width: 200px; height: 200px; border: 1px solid #ccc; } </style> <div class="wrapper"> <div class="inner"></div> </div>
以上代码,在Chrome的测量,inner的高度时202px没有问题,但是外面div的高度是206px,而且可以看见inner底部和父元素之间存在一条缝隙。这条缝隙存在的原因就和inner的对齐方式有关。
在CSS中vertical-align可以设置行内元素的在垂直方向上的对齐方式,按照文档描述,vertical-align可以有以下值:
回到上一个问题,显然inner的对齐方式是baseline,为何baseline的对齐方式会导致一条缝隙呢?查看baseline的定义:
Aligns the baseline of the element with the baseline of its parent.
将目标元素的baseline和父元素的baseline对齐。
首先,如何确定一个元素的baseline?
baseline首先是针对文本的一个概念,小学时刚开始写字母都是在四线三格的本子里写的,其中第三条线(也就是a或者b这种字母的的下边缘对准的线)就是文本的baseline,所以span、strong这种行内元素的baseline就是包含的文本的baseline;
a
b
span
strong
推广到盒元素,包括blobk和inline-block这种有宽高和内外边距的元素,如果内部没有任何子元素,baseline就是这个盒子的下边缘对齐的线,下边缘严格来说是指margin-bottom的边界;
如果盒元素有子元素,但是指定了overflow(非visible),那么baseline仍然是盒子下边缘对齐的线;
如果盒元素有子元素,且没有制定overflow,那么该盒元素的baseline取决于内部最后一个未指定vertical-align的元素的baseline。
但是,上文的例子中,元素的子元素被指定了对齐方式,那元素的baseline取决什么呢? 首先我们想个办法直观的看到父元素的baseline,给父元素添加伪类:
<style> . wrapper::after { content: "x" } </style>
这样可以通过观察x的位置,就可以知道元素的baseline。 在Chrome的元素检查器中查看这个x,可以发现inner的baseline(下边缘)和x的baseline对齐,但是x元素的高度撑开了一个高度造成了父元素比inner更高,从而出现了一条缝隙。 所以可以推测出,如果元素中所有的子元素都制定了对齐方式,那么会默认添加一个空的文本元素,二元素的baseline就是取决于这个文本元素的。
如何去掉这个缝隙呢? 首先可以设置元素的字体大小为0,子元素的字体大小再单独设置,这样这个空的文本元素的高度就是0,也就不会再撑开一个高度了。 还有一个方法就是和这篇文章的主题相关了,既然是inner的对齐方式baseline导致了这条缝隙,我们改变inner的对齐方式试试看。
<style> .inner { vertical-align: sub; } </style>
首先设置为sub,为了直观一些在元素里添加一个子元素<sub>sub</sub>,可以看到inner的baseline是和sub的baseline对其的,而x的baseline向上移动了一些。所以sub的位置是基于元素的baseline的,而inner的baseline和sub元素的baseline对齐;
sub
<sub>sub</sub>
同样的,inner的对齐方式设置为super时,添加一个<sup>sub</sub>观察,发现inner是和sub对齐的,而x的位置向下了一些;
super
<sup>sub</sub>
基于这两种情况下的表现,我们发现父元素的baseline位置是可以被改变的。
当我们将inner设置为text-top时(删除sup和sub元素),发现元素的高和子元素相等了,而x出现在元素上方,查阅文档发现,这种对齐方式和baseline无关:
text-top
Aligns the top of the element with the top of the parent element's font.
将元素的顶部(margin-top)和父元素文本的顶部对齐,x就上移到了靠近元素顶部的位置,而根据baseline的定义方式,此时父元素的baseline也移动到靠近元素顶部的位置。
text-bottom的表现也是相似的,x移动到了元素靠近底部的位置,父元素的baseline也移动到靠近元素底部的位置,之所以是靠近,是因为x文本元素本身有一个高度比字母x更高。
text-bottom
再试一下middle,发现x出现在元素中间位置,文档这样描述的:
middle
Aligns the middle of the element with the baseline plus half the x-height of the parent.
将元素的中间和父元素的baseline + x的一半高度,看文字很难理解,想象在纸上如何画出这个布局:
x
length和percentage两个是相似的,就是在vertical-align: baseline的基础上,偏移指定的距离,其中百分比是根据父元素的额line-height计算出来的,元素的默认行高可以另开一篇。。。
length
percentage
vertical-align: baseline
line-height
最后是top和bottom,文档这样描述他们:
top
bottom
top: Aligns the top of the element and its descendants with the top of the entire line. bottom: Aligns the bottom of the element and its descendants with the bottom of the entire line.
top: 将元素及其后代的顶部和整行的顶部对齐; bottom: 将元素及其后代的顶部和整行的底部对齐。
把top和text-top对比一下发现,差异在于整行的顶部和文字的顶部,如果未指定父元素的行高,这两个的表现是相似的,但是当父元素的行高远大于字体所需要的高度时,top可以保证inner始终顶着父元素顶部,而text-top会在顶部出现空白。
所有元素都存在一个baseline,元素的baseline取决于他的子元素(最后一个未指定对齐方式的子元素的baseline),子元素在垂直方向上的对齐方式由vertical-align决定,其中vertical-align所有的值中,baseline、sub、super、<length>、<%>和baseline紧密相关,top、bottom、text-top、text-bottom和baseline无关,middle严格意义上和baseline也是无关的,描述上是字体高度的一半加上baseline。
vertical-align
baseline
<length>
<%>
有些错误,更新的在#16
行盒子(line box)
所谓行盒子,就是在block元素中,如果存在inline元素,这些inline元素按照顺序排列,宽度不够时会自动换到下一行,每一行就形成了一个inline box。
每一个inline box的高度是由它包含的子元素决定的,直觉上inline box的高度等于最高子元素的高度,但是这是不对的,inlne box的高度还和子元素的对齐方式有关。
以上代码,在Chrome的测量,inner的高度时202px没有问题,但是外面div的高度是206px,而且可以看见inner底部和父元素之间存在一条缝隙。这条缝隙存在的原因就和inner的对齐方式有关。
垂直对齐(vertical-align)
在CSS中vertical-align可以设置行内元素的在垂直方向上的对齐方式,按照文档描述,vertical-align可以有以下值:
回到上一个问题,显然inner的对齐方式是baseline,为何baseline的对齐方式会导致一条缝隙呢?查看baseline的定义:
将目标元素的baseline和父元素的baseline对齐。
首先,如何确定一个元素的baseline?
baseline首先是针对文本的一个概念,小学时刚开始写字母都是在四线三格的本子里写的,其中第三条线(也就是
a
或者b
这种字母的的下边缘对准的线)就是文本的baseline,所以span
、strong
这种行内元素的baseline就是包含的文本的baseline;推广到盒元素,包括blobk和inline-block这种有宽高和内外边距的元素,如果内部没有任何子元素,baseline就是这个盒子的下边缘对齐的线,下边缘严格来说是指margin-bottom的边界;
如果盒元素有子元素,但是指定了overflow(非visible),那么baseline仍然是盒子下边缘对齐的线;
如果盒元素有子元素,且没有制定overflow,那么该盒元素的baseline取决于内部最后一个未指定vertical-align的元素的baseline。
但是,上文的例子中,元素的子元素被指定了对齐方式,那元素的baseline取决什么呢? 首先我们想个办法直观的看到父元素的baseline,给父元素添加伪类:
这样可以通过观察x的位置,就可以知道元素的baseline。 在Chrome的元素检查器中查看这个x,可以发现inner的baseline(下边缘)和x的baseline对齐,但是x元素的高度撑开了一个高度造成了父元素比inner更高,从而出现了一条缝隙。 所以可以推测出,如果元素中所有的子元素都制定了对齐方式,那么会默认添加一个空的文本元素,二元素的baseline就是取决于这个文本元素的。
如何去掉这个缝隙呢? 首先可以设置元素的字体大小为0,子元素的字体大小再单独设置,这样这个空的文本元素的高度就是0,也就不会再撑开一个高度了。 还有一个方法就是和这篇文章的主题相关了,既然是inner的对齐方式baseline导致了这条缝隙,我们改变inner的对齐方式试试看。
首先设置为
sub
,为了直观一些在元素里添加一个子元素<sub>sub</sub>
,可以看到inner的baseline是和sub的baseline对其的,而x的baseline向上移动了一些。所以sub的位置是基于元素的baseline的,而inner的baseline和sub元素的baseline对齐;同样的,inner的对齐方式设置为
super
时,添加一个<sup>sub</sub>
观察,发现inner是和sub对齐的,而x的位置向下了一些;基于这两种情况下的表现,我们发现父元素的baseline位置是可以被改变的。
当我们将inner设置为
text-top
时(删除sup和sub元素),发现元素的高和子元素相等了,而x出现在元素上方,查阅文档发现,这种对齐方式和baseline无关:将元素的顶部(margin-top)和父元素文本的顶部对齐,x就上移到了靠近元素顶部的位置,而根据baseline的定义方式,此时父元素的baseline也移动到靠近元素顶部的位置。
text-bottom
的表现也是相似的,x移动到了元素靠近底部的位置,父元素的baseline也移动到靠近元素底部的位置,之所以是靠近,是因为x文本元素本身有一个高度比字母x更高。再试一下
middle
,发现x出现在元素中间位置,文档这样描述的:将元素的中间和父元素的baseline +
x
的一半高度,看文字很难理解,想象在纸上如何画出这个布局:length
和percentage
两个是相似的,就是在vertical-align: baseline
的基础上,偏移指定的距离,其中百分比是根据父元素的额line-height
计算出来的,元素的默认行高可以另开一篇。。。最后是
top
和bottom
,文档这样描述他们:top: 将元素及其后代的顶部和整行的顶部对齐; bottom: 将元素及其后代的顶部和整行的底部对齐。
把
top
和text-top
对比一下发现,差异在于整行的顶部和文字的顶部,如果未指定父元素的行高,这两个的表现是相似的,但是当父元素的行高远大于字体所需要的高度时,top
可以保证inner始终顶着父元素顶部,而text-top
会在顶部出现空白。总结
所有元素都存在一个baseline,元素的baseline取决于他的子元素(最后一个未指定对齐方式的子元素的baseline),子元素在垂直方向上的对齐方式由
vertical-align
决定,其中vertical-align
所有的值中,baseline
、sub
、super
、<length>
、<%>
和baseline紧密相关,top
、bottom
、text-top
、text-bottom
和baseline无关,middle
严格意义上和baseline也是无关的,描述上是字体高度的一半加上baseline。