← Inline 与 inline-block · 拆解 / 行框 line box vs 行内框 inline box 待审核 1 / 8
concept · line box

行框 line box vs 行内框 inline box

本系列分析的所有现象都建立在这对概念上,先分清:一段 inline 内容在排版时,每个 inline-level 的东西(一截文字、一个 <img>、一个 inline-block)各自是一个 行内框 inline box;浏览器把同一行里的这些 inline box 收拢进一个 行框 line box行框的高度,由这一行里所有行内框按 vertical-align 对齐后「最高顶边到最低底边」的距离决定——不是由某一个盒子单独决定。

**关键:**哪怕一行里只有文字,也有一个看不见的 strut(支柱)——一个高度等于 line-height 的零宽 inline box,默认就把行框撑到至少 line-height 高。这就是为什么「空的一行也有高度」。

但「彻底空」的行不算:规范(CSS 2.2 §9.4.2)的原话是——一个 line box 若既没文字、没保留的空白、也没有带非零 margin/border/padding 的 inline,就被当作零高 line box,而且「视为不存在」。换句话说:上面那个 strut 能撑起高度,前提是这行里有内容(哪怕只是一个空格);若完全为空,这行不占位。这条「有内容才存在」正是 inline-block 间隙(空格 = 内容 → 占一格)和 img 撑高(strut 的 descent)的底层依据。

1 · 动手:把行框撑高的是谁

下面一行里有一段锚文本(带 strut)和两个 inline-block 盒子。拖滑块改两个盒子的高度,看蓝色实线标出的 line box 上下边界:它永远贴着当前最高的那个,高度由最高者决定。把两个盒子都调矮于文字行高时,撑住行框的就轮到那段文字的 strut 了。

2 · 所以「行框高度」到底怎么算

  1. 先把这一行的每个 inline box 量出来:文字用它的 line-height,替换元素 / inline-block 用它的外边距框 margin box 高度。
  2. 按各自的 vertical-align 把它们在垂直方向对齐(默认 baseline,详见 02 · baseline 与 vertical-align)。
  3. 对齐之后,取所有框里最高的顶边最低的底边,两者的距离 = 这个 line box 的高度。
  4. 多行内容就是一摞 line box,行框之间从不重叠——这条性质是负 margin 谜题的最后一块拼图。

注意区分:line-height 设在文字那个 inline box 上;而一个高 200pxinline-block 不管 line-height 多少,都会用它整个 margin box 去撑行框。line box 是「容器行」,inline box 是行里的成员——两者不是同一个东西。

3 · 补两个概念:匿名行内框 与 leading

本系列其余页面会反复用到,这里先说明:

  • 匿名行内框 anonymous inline box:直接写在容器里、没被任何标签包住的裸文字,也会被自动装进一个(匿名的)行内框。像 <div>one two <span>x</span> 三 四</div> 会被切成三段行内框:匿名「one two」+ 具名 span + 匿名「三 四」。匿名框没法直接写样式,它的 font-size / line-height从父容器继承——所以「明明没给文字设行高,它却有高度」就是继承来的。
  • leading / half-leading(行距 / 半行距):line-height > font-size 时,多出来的那部分叫 leading;它被平均分成两半,一半加在文字上方、一半加在下方(half-leading)。所以文字总是垂直居中在自己那个行内框里——这也是为什么纯文字行的高度正好是 line-height,而文字像是浮在行中间。

把这两条接上前文:一行里既有继承了 line-height 的匿名文字框,又有显式设了大 line-height 或大高度的具名框 / inline-block 时,谁高谁定行框高度,其余的按 vertical-align 在里面确定自己的位置。02 · baseline 与 vertical-align 会用一个混合行高的例子(vertical-align: top)把这套规则连成一张图。