9.7 行盒的高度计算

行盒line box的高度计算包含:IFC内各元素的高度与垂直位置,line box的高度计算。


9.7.1 两级IFC属性设置

本节内容特别重要,为全面说明其本质,可能会使用不规范的开发习惯。

IFC四属性包括两级设置:

(1)父div设置。div设置vertical-align无效,所以实际可以设置字体三属性。本质是设置strut bounds的字体三属性,同时其它inline元素也继承这些属性。这是标准做法,养成在块容器设置字体三属性的习惯。

(2)内部inline元素设置。内部inline元素可以设置IFC四属性。通常情况下,不要使用这级设置,可能出现inline元素的bounds与strut bounds的高度与基线不一致,可能撑高line box,可能引起各种混乱。只在极少数情况使用。


9.7.2 line box高度计算方法

示意代码。div、span设置不同line-height,img设置不同高度。

<div>
    <span>span1</span>
    <span>span2</span>
    <img src="xiaobuteach.png">
</div>

line box高度计算包括4步。

(1)计算strut的bounds。根据父div设置的字体三属性计算。

(2)计算各inline-level元素的bounds或盒子。根据继承自父div或自身设置的字体三属性计算;原子行内级别元素以盒子模型进行计算,详情见“9.9 原子行内级盒子”。

前两步示意图如下。

img

(3)垂直对齐。inline-level元素根据vertical-align属性与strut(或line box)进行垂直对齐。假设上述示意图三个元素均基线对齐,对齐后示意图如下。

img

(4)找最上方bounds(包含strut与box)的顶线、找最下方bounds(包含strut与box)的底线,两线之间的距离即line box高度。

img

理解行盒的高度计算过程,就能理解为什么避免在Inline元素设置字体三属性,它们与strut bounds不一致容易导致混乱。


9.7.3 设置span的字体属性撑高行盒

初始代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小步教程</title>

    <style>
        body{
            font-family: Arial;
            font-size: 40px;
            line-height: 50px;
        }
    </style>
</head>
<body>
    <div class="div1">
        <span class="span1">x</span>
        <span class="span2">xiaobuteach.com</span>        
    </div>
</body>

</body>
</html>

查看当前div高度即行盒line box高度50px。

img

span设置line-height值60px。

<span class="span2" style="line-height: 60px;">xiaobuteach.com</span>

查看当前div高度即line box高度60px。

img

结合“IFC模型完整示意图”比较容易理解个别bounds高度撑高行盒。


9.7.4 更小字体因对齐而撑高line box

span元素设置更小字体,可能因后续对齐过程使line box撑高。不是所有更小字体都使line box撑高。

初始代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小步教程</title>

    <style>
        body{
            font-family: Arial;
            font-size: 40px;
            line-height: 50px;
        }
        .div1{
            border-top: 1px solid #4aa6fc;
            border-bottom: 1px solid #4aa6fc;

            position: relative;
        }
        .span1{
            border-top: 3px solid #ed7d31;
            border-bottom: 3px solid #ed7d31;
        }
    </style>
</head>
<body>
    <div class="div1">
        <span class="span1">x</span>
        <span class="span2">xiaobuteach.com</span>
        <div style="top: 39px;position: absolute;width: 100%; border-top: 1px solid #0aaa76;"></div>
    </div>
</body>

</body>
</html>

运行结果

img

其中蓝线与桔块亲密接触,说明第1个x即span1元素的bounds高度等于行高。

注:本例画各条线是为直观显示行高变化与对齐变化。同学们可以不加各border,直接查看div的高度即行高(因为当前只有一行)。


调小字体。span2原先继承的字体大小是40px,现设置span2的字体大小为30px。

<span class="span2" style="font-size: 30px;">xiaobuteach.com</span>

运行效果

img

上图中绿色线依然在x的底部,说明基线位置不变;但span1的下方桔色border与div1的底部蓝色border没有亲密接触,说明行高发生变化:被撑高。

对齐前示意图

img

strut、span1与span2继承div1的line-height,所以它们的bounds高度相同;

因为font-size不同、导致内容高度不同、Leading不同、综合作用基线绝对位置不同, font-size更小的inline元素可能基线更靠上。


对齐过程示意图

img

首先span2下移,然后line box底线也相应下移,导致行盒高度变大。所以,父div的line-height与span的line-height都只是行盒的最小高度。实际项目,外部元素根据需要可能会设置height属性,避免类似调整引起父div高度变化。


试一试。去掉span1元素,测试修改span2字体前后行高的变化。

试一试。编码尝试各种场景验证line box高度计算方法。