9.3 bounds模型

bounds模型是IFC模型的核心之一。inline元素具有bounds模型,line box不具有bounds模型,后续各种示意图可能引起误解,错把bounds模型当成line box的模型。

inline元素的显示与占位。显示按盒子模型,水平方向占位按照盒子模型,垂直方向占位按照bounds模型,bounds设计目的是实现文本在垂直方向的对齐。

术语说明。类似元素与盒子两个术语会混用, inline元素与bounds也会混用。


9.3.1 英语拼写本的4线2距

英语拼写本的线距示意图

img

英语拼写本为帮助书写规范,存在4线2距,实现文字垂直对齐与各行间距。4线如下:

(1)baseline。基线,位于小写x的底部。

(2)x-line。位于小写x的顶部,也称为mean line或median line。

(3)capital line。大写线,位于大写字母的顶部。

(4)descent line。底线,位于小写字母j、g等的底部。

4线对应2个重要距离:

(1)内容区高度。descent line到capital line的距离。

(2)行间空白距离。上一行descent line与下一行captical line的间距Leading,简称L。


9.3.2 bounds模型的7线3距

img

显示屏显示文本比英语拼写本更复杂,设计更多线距,常用有7线3距。此图实际比英语拼写本只多一条ascent line线。存在一些特殊字符比大写英文顶部更高,所以引入ascent line。

L被平分到内容区的上下分别表示,上下各L/2以实现上一行底部与下一行顶部的间距是L,所以上下增加bounds top line与bounds bottom line两条线,则上一行的bounds bottom line与下一行的bounds top line紧挨。

bounds高度是bounds top line到bounds bottom line之间的距离。

bounds高度 = 内容区高度 + 上方L/2 + 下方L/2

内容区高度是ascent line与descent line之间的距离,简记AD;inline元素的bounds高度等于该元素line-height属性值。上述公式简写如下。

bounds line-height = AD + L

区分line box高度与bounds高度。bounds高度是inline元素的高度,line box高度是一行所有inline元素的bounds排列后高度。简单场景下两者相等,并不总是相等。


9.3.3 bounds模型与CSS属性

bounds内容区高度设置通过font-family与font-size间接设置,bounds高度等于该元素的line-height属性值,L等于bounds的line-height减内容区高度,L无需指定也无法指定。这3个属性决定文本的显示,所以CSS设计font复合属性表示这3个原子属性。

当字体大小越大,内容区高度越大;当line-height越大,行间空白间距L会越大。所以inline元素不通过height设置高度、不通过margin设置垂直间距,通过line-height同时设置高度与垂直间距。

字体空白。下图紫线所示,小写x与大写X分别距离上方ascent line的距离不同,这是由字体设计决定的,字体设计每个字符时留下不同高度的空白。

img

9.3.4 bounds内容高度比例

字体文件内部包含字体各项度量信息,可通过FontForge等工具查看。同一字体,内容区高度与font-size总保持固定比例,简称bounds内容高度比例;不同字体,bounds内容高度比例不同。

示例代码

<!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: 20px;
            line-height: 30px;
        }
    </style>
</head>

<body>
    <div>
        <span>xiaobuteach.com</span>
    </div>
</body>

</html>

假设已知字体Arial的bounds内容高度比例等于1.12,则绝对值等于20*1.12=22.4,取整22px。当inline元素没有设置padding与border时,盒子高度等于bounds内容区高度,也就是通过盒子高度间接测算bounds内容区高度。开发者工具查看span元素高度22px,与分析一致。

img


反推bounds内容高度比例。bounds内容高度比例可通过FontForge工具读取字体度量信息然后计算。这里直接用反推法计算:font-size设为100px再查看bounds内容高度,反推比例。将font-size改为100px,查看盒子高度112px,反推bounds内容高度比=112/100=1.12。

试一试。将字体换成宋体、微软雅黑,分别测试bounds内容高度比。


9.3.5 高度关键数据

bounds高度。当前单行且无其padding/border设置,所以bounds高度=行盒高度=父div高度,即bounds高度=父div高度。

img

桔线与绿色之间的间距等于(30-22)/2=4px,也就是bounds模型标记的L/2高度。

总结bounds高度关键数据:

(1)基础数据。字体名称Arial,Arial字体的bounds内容高度比1.12,font-size20px。

(2)bounds内容高度。等于font-size * bounds内容高度比例 = 22px。

(3)bounds高度。等于继承父div的line-height值 = 30px。

(4)bounds上下空白L/2。等于 (30 -22)/2 = 4px。


9.3.6 默认line-height

当inline元素没有设置也没有从祖先元素继承line-height值,则从字体文件读取默认line-height。字体文件的度量信息不仅可以计算bounds内容高度比例,还能计算默认的bounds高度比例(即默认line-height)。也可以说,每个字体提供了默认line-height。不同字体的默认line-height不同。通过FontForge查询Arial字体信息计算得出bounds高度1.15,则外部div的高度等于20*1.15=23px。

L值分配不均。对应L值=23-22=1px。如果L值是偶数,则上下平分;L值1px不够上下进行整数的平分,会分配给谁?CSS规范没有规定这么细致,不同浏览器有不同做法。Chrome浏览器显示如下,span与div底部不对齐,说明分配到下方。

img

Firefox浏览器显示如下,span与div顶部不对齐,说明分配到上方。

img

实际项目一定会设置line-height属性值,所以line-height默认值主要是研究用。

试一试。与反推bounds内容高度比例类似,反推宋体与微软雅默两种字体的默认line-height比例值。


9.3.7 bounds模型核心公式总结

bounds内容高度 = font-size * font-family的内容高度比
bounds高度 = line-height属性绝对值 
line-height属性绝对值 = font-size * line-height比例值
上下空白间距L/2 = (bounds高度 - bounds内容高度) / 2
line-height默认值 由 font-family 提供