为什么空白的 inline-block 元素会创建高度,而空白的 inline 和 block 元素不会?

去年2月份的时候在思否刷到一个问题 👉 span的display为inline-block 和inline的时候对父级元素高度的影响?
当时就觉得很奇怪,以为是一些其他的CSS属性影响导致的,但是问题后面提到了参考链接里面具体说了原因,只不过OP没有很好的理解,我也没有很好的理解。
因为就算是IFC的问题,inline-blockinline 元素的表现应该是差不多的。但是实际情况并不是这样,只有 inline-block 是特殊的情况。

一年多的时光中有几次想捋清楚这个问题,但是又因为各种借口搁置了,今天终于逮起劲来准备解决掉这个疑惑。

以下是当时写的一个复现Demo,只会显示子元素是 inline-block.container 会有高度(显示红色)。而子元素的 inlineblock.container 并没有高度,所以不会显示(蓝色和绿色)。

不同display类型的预览图

很奇怪是不是?你也可以复制下面的简单HTML代码在自己的本地复现这个问题:

<div class="container red">
  <div style="display: inline-block"></div>
</div>
<div class="container blue">
  <div style="display: inline"></div>
</div>
<div class="container green">
  <div style="display: block"></div>
</div>

<style>
.red {
  background-color: red;
}
.blue {
  background-color: blue;
}
.green {
  background-color: green;
}
</style>

那么继续阅读问题中引用的文章内容。可以看到作者排查的思路:

  1. 外部的 <div> 元素的高度计算;
  2. 依赖内部包含的非块级元素高度;
  3. 非块级元素需要计算 line box 高度;
  4. line box 的高度依赖 line-height 的高度;
  5. 空的行内元素依赖 strut 的高度;
  6. strut 的高度计算

简略版的看起来是不是有点不明所以,具体可以 查看博客原文

所以引起这个问题的原因是因为:

Empty inline elements generate empty inline boxes, but these boxes still have margins, padding, borders and a line height, and thus influence these calculations just like elements with content.
空的行内元素会生成空的行内框,但这些框仍然有边距、内边距、边框和行高,因此会像有内容的元素一样影响这些计算。

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.” (The name is inspired by TeX.).
在块容器元素上 其内容 由内联级别组成 对于元素,line-height 属性指定元素内各行框的最小高度。最小高度由基线以上的最小高度和基线以下的最小深度组成,就像每个行框都以一个宽度为零的行内框开始,并应用元素的字体和行高属性一样。 我们将这个虚拟的框称为“支撑框”(strut)。(这个名称源自 TeX。)

那么聪明的你肯定会问了!

❓ 那么同样为行内元素的 inline 不会撑开外部元素的高度呢?

那是因为规范定义这部分的情况,被强制忽略了。

Line boxes are created as needed to hold inline-level content within an inline formatting context. Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose.
行框根据需要创建,用于在行内格式上下文中容纳行内内容。如果行框不包含任何文本、不包含任何保留的空白、 不包含任何具有非零边距、内边距或边框的行内元素,也不包含任何其他内流内容(例如图像、行内块或行内表格),并且没有以保留的换行符结尾,则在确定其内部任何元素的位置时,必须将其视为零高度行框;在任何其他情况下,都应将其视为不存在。


📚 相关文档

#10.6.3 Block-level non-replaced elements in normal flow when ‘overflow’ computes to ‘visible’ | Visual formatting model details - W3C Working Draft
#9.4.2 Inline formatting contexts | Visual formatting model - W3C Working Draft
#10.8 Line height calculations: the ‘line-height’ and ‘vertical-align’ properties | Visual formatting model - W3C Working Draft
#strut | Visual formatting model details - W3C Working Draft

其他资源

inline-block 元素高度为0,父级仍被撑起,问题元凶 —— strut - CSDN博客
html - 没有高度的inline-block,父元素却有高度 - SegmentFault 思否
html - Why Empty Display Inline Block Element Create Height But Display Inline and Display Block not? - Stack Overflow
html - How to determine height of content-box of a block and inline element - Stack Overflow
[css-display] Should ‘run-in flow-root’ blockify to ‘block’ or ‘flow-root’? · Issue #1715 · w3c/csswg-drafts