JuniorTour / blog

not only front-end
8 stars 5 forks source link

详解 line-height 属性 —— HTML中一行文字是如何排布的?什么是内容区、行内框、行框? #3

Open JuniorTour opened 4 years ago

JuniorTour commented 4 years ago

一位前端工程师,写过的最多的代码一定是<div>, <span>等填满了文字内容的HTML标签,那么各位有没有想过在这些标签内的文字是如何排布的?

本文将详细介绍line-height、font-size等属性的来龙去脉,以及em框、内容区、行内框和行框等概念,深入剖析这一行文字在毫厘之中的奥秘。

1. font-size:生成 em框 与 内容区

首先,一个字符受字体内置配置以及 font-size 属性影响,会在其周围产生一个不可见的em框(em square)(如下图),font-size属性并不决定实际显示的字符尺寸,只是指定 em框 的高度(宽度则会因字符、字体不同,而不尽相同)。

em框与其中字符的具体大小、相对位置关系由字体内置值决定。

也就是说对于不同的字体,即使是同样 font-size 的同一个字符也会产生不同尺寸的em框,并与em框有不同的相对位置。

一个元素中多个字符的 em 框组合在一起,就形成了内容区,即下图粉色外边框所圈起来的部分。 内容区的高度就是 font-size 的值,而宽度则视内容(如一行中文字的个数)而定。

em-box-and-content-area

em 框的概念来自传统印刷行业,以下图为例,为了用活字字模组成一块整齐的印刷板,每个字模的高度必须保持一致,这个高度称为em,即大写字母M对应字模的高度。

MetalTypeZoomIn

参考资料:Design with FontForge: EM square

2. line-height和基线

line-height 属性的值规定的是两行文字基线之间的最小距离。

基线也是印刷行业中的术语,维基百科这样描述它:“A baseline is a line that is a base for measurement or for construction.”(基线是一条用于测量和构造的线)。

基线相当于一把尺子,水平地串在 em 框里,一个个字符就以基线为参照,整齐地“站”在基线上(如下图)。

baseline-line-height

基线的位置因字体而异,由字体内置值决定位于 em 框中特定的位置,如下图:

where-is-baseline

因为基线无法在浏览器中看到,所以我们以上图中每行文字的 underline 为参照来看基线,上述三行分别为不同的字体,但有相同的 font-size 。

这三行中相同的字,如落、孤,可以明显地看到与基线有着不同的位置关系,第一行字底部与基线有一点重合,而其余两行则和基线几乎没有重合。

因为这三种字体的基线在 em 框之中的位置是不同的。

声明line-height 属性后,两行文字的基线便按照这个值上下分开,行与行也相应的上下分开。

当行高大于字体高度,即line-height的值减去font-size的值大于0时,基线相隔的距离大于该行的行框高度时,两行文字便被分开。

l-h-big-than-f-s

当行高小于字体高度,即 line-height 的值减去 font-size 的值小于0时,基线相隔的距离小于该行的行框高度时,两行文字便会重合在一起。

line-height-small-than-font-size

3. 行间距、行内框与行框是什么

内容区的上下还会有行间距(leading),具体值为行高减去字符大小的一半,( line-height 减 font-size 除 2 )。 行间距可能是负值(行高小于字符尺寸),这时就会产生上图所呈现的行与行相互重合的现象。

行内框内容区行间距,其高度的计算公式是:font-size + (line-height - font-size),去掉括号即 line-height,也就是说行内框的高度就等于 line-height 的值。

同一行中可以有不同高度的行内框(如下图)。

行框的上边界由最高的行内框决定,下边界由最低的行内框决定。

line-box-1

4. 行与行之间最终的相对位置

一个行框包含着一整行的内容,各个行框之间上下紧密贴合排列,形成了最终呈现在页面上行与行之间的位置关系。

总结:

参考资料:
  1. 《CSS 权威指南(第三版)》,第六章、文本属性和第七章、视觉格式化

  2. W3C规范-9 Visual formatting model(可视化模型)/ 中文版

  3. 另一篇同样主题的博文:深入理解CSS中的行高,相互对照,加深理解。

  4. 慕课网上张鑫旭老师的两节课:line-height与内联元素的高度机制

Aze-ziv commented 3 years ago

应该是不同字体也产生一样的em框,只是不同字体在同样em框里的位置和大小等定义不一样吧

JuniorTour commented 3 years ago

应该是不同字体也产生一样的em框,只是不同字体在同样em框里的位置和大小等定义不一样吧

@Aze-ziv 你好,就我查到的一些资料来看,em框的尺寸是由字体自定义的,不同的字体应该会产生不同尺寸的em框。

参考资料:

Em-box vs the content-area of a non-replaced element:The em-box is the theoretical box (or square) around a font character of a given 'size' as designed by the font designer.

《CSS 权威指南 4th》中文翻译:Most fonts, as it turns out, don’t have em boxes whose heights match the character glyphs.

Aze-ziv commented 3 years ago

感谢;那我们的font-size设置的就不是em框的大小了吧,有些奇怪

Aze-ziv commented 3 years ago

Most fonts, as it turns out, don’t have em boxes whose heights match the character glyphs.:意指同个字的不同字体的字形(可视文字)与em框没有一个确定的关系;但是这个em框应该是和我们的font-size大小一样,不然怎么理解我们font-size如果设置为16px的em框大小呢

Aze-ziv commented 3 years ago

1 如图设置字体line-height:1em;height:1em;font-size:200px; 与另一背景为200px高的方框同高,可理解为:em = font-size;则不同字体em框应该是一同大的

JuniorTour commented 3 years ago

1 如图设置字体line-height:1em;height:1em;font-size:200px; 与另一背景为200px高的方框同高,可理解为:em = font-size;则不同字体em框应该是一同大的

你好,我的理解是 font-size属性的值,指定的是 em框高度,而em框的宽度则是不同的字体、不同的字符各不相同。

所以不同字体em框应该是一同大的这个理解可能并不正确, 个人认为正确的应该是:不同字体em框宽高不尽相等

DEMO:https://jsbin.com/qozugihuci/edit?html,output image

也可以参考正文中的这一段: image

Aze-ziv commented 3 years ago

感谢您的回答,是我的表述存在一些问题,em框的高度应该是相同的,我赞同您的观点