文章地址:https://github.com/afishhhhh/blog/issues/4
一个例子
![](https://img.haomeiwen.com/i975510/5de5055463eba52f.png)
div { background: #eee; border: 1px solid #000; box-sizing: border-box; }
<div><img src="./image.png" alt=""></div>
在图片中可以看到 <img>
与外层的 <div>
存在一个间隙,这是因为浏览器认为每一个 line box 的起始位置都存在一个宽度为 0 的,没有任何字符的 匿名 inline box(下文会提到的 strut),也就是说这个 匿名 inline box 的高度会影响整个 line box 高度的计算。
在这个例子中 <img>
作为一个可替换的行内元素,在默认情况下他的底边与父元素的 baseline 对齐。而这个父元素的 baseline 所在的位置就是父元素中字母 x 底端所在的位置。如下图所示:
![](https://img.haomeiwen.com/i975510/654388c790825945.png)
上文所说的 strut 其实就相当于一个不可见的字母 x,父元素的基线就是 strut 的基线所在的位置。而 strut 本身是具有 line-height 的,所以就导致图片底部多了一段间隙。
总结一下存在间隙原因:
- strut 存在 line-height
- vertical-align 默认值为 baseline
对应的解决方案:
- 修改 strut 的 line-height,因为 strut 的 line-height 不是能够直接设置的,所以需要设置父元素的 line-height,然后让 strut 继承,或者修改 font-size
- 将 vertical-align 设置为其他值
IFC
![](https://img.haomeiwen.com/i975510/3a6c057aaf663fe3.png)
<div>我是一个匿名 inline box <em>我是一个 inline box</em> 我是另一个匿名 inline box</div>
IFC 中有两种盒子:inline-level box 和 line box。多个 inline-level box 组成了一个 line box。
line box 高度计算
- 浏览器会计算 line box 中每一个 inline-level box 的高度,对于不同的 inline-level box 计算方式有所不同。如果是一个替换元素,高度由其 margin box 决定,如果是一个非替换元素,高度由它的 line-height 决定。
- line box 中所有 inline-level box 的最高点以及最低点决定了它的高度(该计算包括了 strut 的高度,后文 line-height 中提到 strut)。
以上文的图片作为例子:
<img>
所在的 line box 最高点是图片的顶部,最低点是 strut 的底部。<img>
作为一个 inline-level box,它的高度就是图片的高度,而 strut 其实就是个普通的文字,再加上 vertical-align: baseline 的作用,最终撑开了整个 line box。多个 line box 堆叠起来就撑开了父元素的高度,在这里只有一个 line box,撑开了 <div>
的高度。
- 非替换元素的的 margin,padding 以及 border 并不会影响 line box 高度的计算。当一个 inline-level box 的 line-height 小于 content area 的时候,line box 的高度就会小于 content area(line box 的高度与 content area 是没有关系的),此时元素的 background 以及 padding 等就会溢出到 line box 之外。
以下代码可以说明这个问题:
div {
background: #eee;
border: 1px solid #000;
box-sizing: border-box;
font-size: 50px;
line-height: 10px;
}
span {
background: red;
margin: 10px;
padding: 10px;
}
<div><span>xxx</span></div>
![](https://img.haomeiwen.com/i975510/b0bd738230119ae7.png)
line-height
W3C 中对于 line-height 的解释是这样的:
On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element. The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height properties. We call that imaginary box a "strut."
我的简单理解是,对于由行内元素组成的块级元素而言,line-height 决定了 line box 的最小高度,浏览器会假定每一个 line box 以一个宽度为 0 的 inline box (strut)开始,而这个 strut 从父元素继承到 font 以及 line-height。(issue 开头的例子就是 strut 造成的)
- normal 是 line-height 的默认值,W3C 对它的定义是一个介于 1.0 到 1.2 的数值(并没有看懂)。根据另一篇文章的解释,normal 与字体本身有一定关系。
- line-height 并不是两条 baseline 之间的距离。
line-height
的值推荐使用数值,而不是使用 em 单位,因为 em 单位会根据从父元素继承到的 font-size
来计算行高。
vertical-align
W3C 对 baseline 以及 middle 的定义如下:
baseline: Align the baseline of the box with the baseline of the parent box. If the box does not have a baseline, align the bottom margin edge with the parent's baseline.
元素基线与父元素基线对齐,如果元素没有基线,比如 <img>
,则使用 margin 底边与父元素基线对齐。
middle: Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.
元素的垂直中点位置与父元素的基线加上一半 x-height 的位置对齐。
参考
https://www.zhangxinxu.com/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height/
https://zhuanlan.zhihu.com/p/25808995
https://www.w3.org/TR/CSS2/visudet.html#inline-box-height
网友评论