1.情景再现
在调整css统一规范的时候发现一个问题,先贴代码:
js
<div class="item">
<div class="flex-div">sssss</div>
<span class="desc">hhhhhh</span>
</div>
<style scoped>
.item {
line-height: 32px;
}
.flex-div {
display: flex;
align-items: center;
flex-direction: column;
background-color: gray;
}
.desc {
display: inline-block;
line-height: 18px;
background: red;
}
</style>

这一段代码的意思是用一个line-height:32px的外层div包裹了一个flex布局的div和一个span标签。
此外还根据具体的业务需求对flex和span标签进行了样式改造。
但是很容易就发现好像span标签中的line-height:18px没有生效,图中sss和hhh之间明显有一段空白,乍一看line-height还是32px,没被18px覆盖。
2.问题定位及原因分析
经过f12审查元素后发现sssss
行高确实为32px,hhhhh
行高也为修改后的18px。但为什么会出现一块空白呢?
知识点引入
- 基线
字母 x 的下边缘(线)就是基线

在 CSS 中有两个重要属性,line-height
和vertical-align
都与基线有关,line-height
行高的定义就是两个基线之间的距离,vertical-align
的默认值就baseline
,也就是基线对齐。对于内联元素而言,虽然vertical-align
与line-height
看不见,但实际上到处都是!
- 幽灵空白节点
在 HTML5 规范中有这样一句话:
"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'."
每个行框盒子都以一个具有元素的字体和行高属性的零宽度行内框开始。我们称这个假想的盒子为"支柱"。
在HTML5 文档声明 中,内联元素的所有解析和渲染表现就如同每个行框盒子的前面有一个"空白节点"一样。这个"空白节点"永远透明,不占据任何宽度,看不见也无法通过脚本获取,就好像幽灵一样,但又确确实实地存在,表现如同文本节点一样,因此,在张鑫旭大佬的《CSS 世界》一书中根据特点,将其称之为"幽灵空白节点",也就是官方规范中的"strut
"。
- line-boxes
在 line box 模型中,inline boxes
的高度直接受line-height
控制,而真正的高度表现则是由每行众多的inline boxes
(等于内部最高的inline box
的高度),而这些line boxes
的高度垂直堆叠形成了containing box
的高度,也就是我们见到的<p>
或者<div>
标签的高度。
根据以上知识点抛出一些个人猜想:
- 对于内联元素,
vertical-align
的默认值是baseline
,也就是基线对齐,所以<div>
和span
中的元素都是以下边缘对齐。对于行内文本,每个框盒子有一个默认的基线对齐。而行高正是由基线到基线之间的距离来计算的。 - 在上述代码中,
.item
容器的行高被设置为32px
,而<span>
标签的文本框的基线与.item
容器的基线之间有一个距离差。这种差异会导致幽灵空白节点的计算结果与基线之间出现空隙。这个空隙在页面上会被呈现为两段之间的额外垂直距离。
3.解决办法
- 让
vertical-align
失效:vertical-align
属性对于块级元素是无感的,因此我们只需要为元素设置dispaly
为block
即可; - 修改
vertical-align
属性值为:top
,修改其默认值baseline
值为其他属性值,使其不再相对基线对齐; - 修改
line-height
的值:上面我们说过line-height
的定义是两基线之间的距离,因此在上面例子中,两段之间空隙实际上是"幽灵空白节点"计算后的行高值和基线的距离,因此,只要line-height
足够小,便可以消除空隙。(注意这里是要在div
上设置line-heght
,然后让div
的inline boxes
继承line-height
属性)
修改后:

4.参考来源
- 带你探索神秘的"幽灵空白节点" zhuanlan.zhihu.com/p/391118319
- CSS中的幽灵空白节点 blog.csdn.net/zz132685708...