行盒的概念 - line boxes

一个div没有设置高度的时候,会不会有高度?

  • 没有内容,没有高度
  • 有内容,内容撑起来高度

但是内容撑起来高度的本质是什么呢?

  • 内容有行高(line-height),撑起来了div的高度

行高为什么可以撑起 div 的高度?

  • 这是因为存在行盒 line boxes,并且 line-boxes 有一个特性,行盒一定要包裹所有的行内级内容
  • 对于文字,文字是有行高的,必须将整个行高包裹进去,才算包裹这个行内级内容

行内级内容的多种情况

情况一:只有文字时(注意:红色是包裹的div,下面也都一样)
image.png
情况二:有图片,有文字时
image.png
情况三:有图片,有文字,有inline-block(比图片要大)
image.png
情况四:有图片,有文字,有inline-block(比图片要大)而且 inline-block 设置了margin-bottom
image.png
情况五:有图片、文字、inline-block(比图片要大)而且设置了margin-bottom并且有文字
image.png

结论:无论什么情况,行盒一定要包裹所有行内级的内容

CSS属性 - vertical-align

行盒一定要包裹所有的行内级的内容,而行内级内容在垂直方向上的对齐方式,则是通过 vertical-align 来设置
image.png
image.png

默认基线对齐 baseline

vertical-align 的默认值,就是 baseline
image.png

基线 baseline

默认基线对齐导致了行内级内容对齐的千奇百怪,那行内级内容的基线分别是哪里?

  1. 文本的 baseline 是小写字母 x 的底部

image.png
因为文字的基线不是文字的最底部,所以图片和文字在一起的时候,图片下面会出现一条缝

  • 解决图片下边缘的间隙方法:
    • 方法一: 设置成top/middle/bottom
    • 方法二: 将图片设置为block元素
  1. Inline-block 默认的 baseline 是 margin-bottom 的底部(没有,就是盒子的底部)

  2. Inline-block 有文本时,baseline 是最后一行文本的基线

    • 这个基线位置解释了行内级内容的多种情况中情况5的发生。

由此可知行内级元素对齐不要使用 vertical-align,因为基线会变,所以很容易乱。

vertical-align 的属性值

  • baseline(默认值):基线对齐
  • top:将当前行内级盒子的顶部跟第一个行盒的顶部对齐
  • middle:将当前行内级盒子的中心线 与 父盒基线加上 x 字母高度一半 的线对齐
    • 父盒基线也就是同行的其他行级内容所构成的基线
    • 字母 x 肯定刚好就在基线上,加上 x 字母高度一半,也就是 middle 是和字母 x 这个叉的交点对齐
  • bottom:把行内级盒子的底部跟line box底部对齐
  • :把行内级盒子提升或者下降一段距离(距离相对于line-height计算\元素高度), 0%意味着同baseline一样
  • :把行内级盒子提升或者下降一段距离,0cm意味着同baseline一样

    vertical-align: top;

    注意:设置对齐方式是给行内级元素自身设置 vertical-align 属性。同一行的其他行内级元素依然是保持基线对齐。
    image.png

    vertical-align: middle; 设置行内元素垂直居中

vertical-align: middle; 压根不存在居中的概念。一般居中指的是上下存在空隙,然后让一个小一点的元素居中,可是行盒必须刚好包裹内容,比如图片,图片撑满了行盒高度,这还怎么居中。

而且 middle 的对齐方式指的是:和字母 x 这个叉的交点对齐

  • 那只要让 x 字母这个交点在中线,middle 不就能设置居中了吗?

这可能会让人立即联想到 line-height 和父盒子高度相等,文字居中。这可以让文字居中,但是很遗憾,字母 x 的交叉点并不在中线上,因为字体存在文本下沉。字母 x 的交叉点在中线下面一点点。
image.png
所以,vertical-align: middle; 不能实现垂直居中。

带文本的行内块元素居中

假设父盒子中有文字和图片为兄弟元素。
设置 line-hight 也就是行盒高度和父盒高度相等,浏览器就会平分行距,让文字居中。而此时图片就没有不会居中,会顶贴着行盒顶部也就是父盒顶部。为此,我们为了让图片居中可能会设置 middle 让图片看起来居中了。

但是假如把图片换成包含文本的行内块元素,比如 span 包裹文字,转换成行内块元素,且文字在 span 中居中,并且文字大小和父元素中文字大小一样,那 span 就会垂直居中。
因为 vertical-align 的默认值 baseline 在发挥作用,它会让 span 包裹的文字基线对齐父元素中居中的文字,因为文字本身在 span 这个行内块中就是居中的,顺带着就让 span 也居中了。有种 a=b=c 的感觉。

注意两个前提:

  1. 行内块中文字要和父元素中文字大小一样,假设文字变大了,基线要保持一致,可是文字变大,导致行内块的中线往上提了,不再和父元素的中线重合。
  2. 文字在行内块中居中,因为文字不在行内块居中,到时候文字居中了,行内块也会不居中,两者脱钩了。

点击查看【codepen】