文章 GitHub 地址:https://github.com/afishhhhh/blog/issues/4
文章若有错误,请各位可以指出。css
经过一段代码能够理解一下:html
div { background-color: #ccc; font-size: 20px; color: #fff; } span { color: red; } <div>文字1<span>文字2</span>文字3</div>
白色的文字就是一个匿名 inline box,红色的文字是一个由 span
包裹的 inline box。这三个 inline box 组成一个 line box,能够理解为灰色的区域,由于在这个例子里就是由一个 line box 撑开了 div
。若是有多行的文字,那就有多个 line box。git
关于 content area,W3C 有一段这样的解释:github
CSS 2.1 does not define what the content area of an inline box is (see 10.6.1 above) and thus different UAs may draw the backgrounds and borders in different places.
这篇文章对非替换元素 content area 的定义就是自有宽高加上 margin,padding 以及 border。我认为应该将 content area 理解为 content box。web
浏览器会计算 line box 中每个 inline box 的高度,对于不一样的 inline box 计算方式有所不一样:浏览器
若是是一个替换元素(好比 img
,input
),inline-* 元素或者是 flexbox 中的子元素,高度由其 margin box 决定;wordpress
inline-block 元素:字体
div { background-color: #ccc; color: #fff; } span { display: inline-block; height: 30px; margin: 10px; background: #fff; color: red; } <div>xxx<span>xxx</span>xxx</div>
这里 span
inline box 的高度就是 height + margin 2。若是 height 的值是 auto,高度就是等于 line-height + margin 2。flex
若是是一个非替换元素,高度由它的 line-height 决定,而不是 content area,虽然有时候看起来像 content area 撑开了 line box 的高度。flexbox
div { background-color: #ccc; font-size: 20px; color: #fff; font-family: Sana; } span { background: #fff; color: red; } <div>xxx<span>xxx</span>xxx</div>
这张图片能够明显地看出撑开 line box 的是 line-height,而不是 content area。
这篇文章用了 virtual-area height 来表示 line-height 撑开的高度,而个人理解其实就是 inline box 的高度。
非替换元素的的 margin,padding 以及 border 并不会影响 line box 高度的计算。当一个 inline-level box 的 line-height 小于 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>
content area 的高度与 inline box 的高度差就是 leading,这个 leading 会等分被添加到 content area 的顶部与底部,因此说 content area 永远位于 inline box 的中间(垂直居中)。
浏览器认为每个 line box 的起始位置都存在一个宽度为 0,没有任何字符的 匿名 inline box,称为 strut,这个 strut 是会从父元素继承 line-height 的,所以它的高度会影响整个 line box 高度的计算。
div { background: #eee; border: 1px solid #000; box-sizing: border-box; } <div><img src="./image.png" alt=""></div>
在图片中能够看到 img
与外层的 div
存在一个间隙,这就是上文提到的 strut 形成的。
在这个例子中,默认状况下 img
的底边与父元素的基线对齐(img { vertical-align: baseline }
),而这个基线实际上就是 strut 基线所在的位置。以下图所示:
strut 其实就至关于一个不可见的字母 x,上文已经提到 strut 自己是具备 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。
line-height
的值推荐使用数值,而不是使用 em 单位,由于 em 单位会根据从父元素继承到的 font-size
来计算行高。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 的位置对齐。