display 双值语法与基线间隙
display 的取值实际上是两个独立的概念:outer display type 决定这个盒子如何参与父级的布局,inner display type 决定它如何布置自己的子内容。block / inline-block / flex 这些熟悉的单值写法是简写,双值语法把两半拆开写:block flow、inline flow-root、block flex。
1 · 单值与双值的对应
计算值层面二者完全等价。实测 display: block flow 读回的计算值是 block,display: inline flow-root 读回的是 inline-block(Chrome 152,核对于 2026-09)——浏览器把双值折回最接近的单值关键字,getComputedStyle 里看不出作者写的是哪一种。
| 单值 | 双值 | outer | inner |
|---|---|---|---|
block |
block flow |
block | flow |
flow-root |
block flow-root |
block | flow-root |
inline-block |
inline flow-root |
inline | flow-root |
inline |
inline flow |
inline | flow |
2 · 这条声明在 textarea 上改变了什么
UA stylesheet 给 <textarea> 的是 inline-block,外部显示类型是 inline,控件因此坐在一个行框里。行框要为字体的 descender 留出空间,控件底部于是多出一段与文字无关的留白:一个高 36px 的控件放进 line-height: 1.5 的 16px 容器,容器实测高 42px,多出的 6px 就是这段间隙。
改成 block 之后控件不再参与行框布局,容器高度回到 36px,与控件严丝合缝。这也是配方把它放在第一条的理由:后面几条都在调尺寸,而尺寸对不上的第一嫌疑往往不是尺寸本身,是这 6px。
3 · 内部显示类型的去向
配方写的是 block flow 而不是 block flow-root,字面含义是「内部按常规流布置子内容,且不建立 BFC」。这个区别在 <textarea> 上观察不到:控件的内容由 UA 生成的内部结构承载,作者的 inner display type 并不下发到那一层。图 2-1 里 block 与
block flow 两档的盒高、控件高、计算值三项读数逐字相同。
所以这条声明真正起作用的只有 outer 那一半。写成双值的收益是表意——读到 block flow 的人知道作者是在选外部显示类型,而不是顺手抄了个 block。
警示 · 双值写法的浏览器支持晚于单值:Chromium 115(2023-07)、Firefox 70(2019-10)、Safari 15(2021-09)(兼容性据 MDN BCD,核对于 2026-09)。不认识双值语法的浏览器会把整条声明当作无效值丢弃,而不是退回 block——控件将保持 UA 的 inline-block,那 6px
间隙也就还在。需要覆盖更旧的版本时,前面补一行单值 display: block 作垫底。