真的理解font-size和line-height了吗?

希沃ENOW大前端css

公司官网:CVTE(广州视源股份)html

团队:CVTE旗下将来教育希沃软件平台中心enow团队前端

本文做者:api

龙飞名片.png

前言

line-heightfont-size都是你们在平常开发过程当中常常用到的css属性,可是有多少人知道fontsize设置100px,表明什么意思呢? 它跟元素高度和line-height是什么关系呢? 还有咱们常常将line-height设置父容器的高度来实现文本垂直居中对齐,它的原理是怎样的呢,带着这些问题,咱们来探讨一下。浏览器

font-size

font-size其实表明的是字体的高度,若是不一样的字体设置相同的font-size,字体高度会同样么,咱们来举个例子看一下: 下面是一段简单的 HTML 代码,一个 p 标签包含了 3 个 span 标签,每一个 span 各自有一个 font-familymarkdown

<p>
    <span class="a">Ba</span>
    <span class="b">Ba</span>
    <span class="c">Ba</span>
</p>
p { font-size: 100px }
.a { font-family: Helvetica }
.b { font-family: Gruppo    }
.c { font-family: Catamaran }
复制代码

font-size 相同,font-family 不一样,结果发现获得的 span 元素的高度也不一样,通过测量发现: Helvetica 115px,Gruppo 97px,Catamaran 164pxoop

image.png

为何会这样呢,想要找到答案,咱们要先了解字体的原理。字体

字体原理

  1. 一款字体首先会定义一个em-square,它是用来盛放字符的金属容器。这个 em-square 通常被设定为宽高均为 1000 相对单位,不过也能够是 102四、2048 相对单位。你能够理解为字体的模板(字模),以下图所示:

image.png

  1. 每一个字体会定义5条度量线来控制字符的位置,其中包括 ascender、descender、capital height、x-height,baseline 这5条度量线,这些度量的刻度是基于1000这个相对单位(不一样字体相对单位可能不同)来设置的,以下图所示:

image.png

  • Baseline: 就是咱们常说的基线,全部字母放置的水平线。它是文本中一条稳定的轴线,是校准文本与图片,文本与文本的一条重要的参考线。其余度量线都是相对基线来计算的。
  • X-Height: 是主要的小写字母高度(或者说是“x”字母的高度),除去上延和下延部分
  • Cap Height: Capcapital(大写字母)的简称,有时也用capital height全称,是指H或E等直线型大写字母从基线到字母顶部的高度(大写字母高度)。而H或E等顶部这条对齐线叫做都大写线(cap line
  • Ascender: 升部线,某些小写字母(例如h、l)会有一个升部(也叫上延),高度超出x-height,这是升部的对齐线
  • Descender: 降部线,某些小写字母(例如p、y)会有一个降部(也叫下延),沿基线往下延长的部分,这是降部的对齐线

其中,AscenderDescender之差决定了字体渲染的高度(不考虑行高),也就是下文将会提到的content-area(内容区域)的高度spa

  1. 在浏览器中,上面的 1000 相对单位会按照你须要的 font-size 缩放。

为了作更好的分析,咱们装一下FontForge软件,看一下具体字体的字体度量信息。设计

具体的例子

FontForge软件打开某个字体,通常咱们能够看到这样的设置:

image.png

Units Per Em(就是上文讲到的em-square)表示一个字的高度有1000个单位,baseline的坐标为0,其它线的坐标相对于baseline,以下图所示:

image.png 不一样字体的字体度量是不同的,咱们来分析一下上面例子用到的Catamaran字体: image.png

Em Size(也就是em-square): 1000,ascender : 1100,descender : 540macOS 上的浏览器使用了 HHead AscentHHead Descent 值,Windows 上的浏览器使用了 Win AscentWin Descent(并且两个平台上的值不同)。

这意味着 Catamaran 字体占据了 1100 + 540 个相对单位,尽管它的 em-square 只有 1000 个相对单位,因此当咱们设置 font-size:100px 时,这个字体里的文字高度是 1640*100/1000 = 164px ;另外咱们也能算出大写字母的高度(cap height)是:680*100px/1000 = 68px;小写字母的高度(x-height)是 485*100/1000=49px,以下图所示:

image.png

总结

  1. fontsize 的值不表明字体高度,也不表明的字体内容(content-area)高度
  2. 字体内容(content-area)高度 与 font-sizefont-family 相关

line-height

line-height ,又称行高,指的是两行文字基线之间的距离,也能够称为这行文字所占的高度。

image.png 要理解line-height,咱们首先要先理解行内框盒子模型,如下咱们会详细介绍具体的4种盒子。

行内框盒子模型

  1. 内容区域(content area):是一种围绕文字看不见的盒子。内容区域的大小与font-size大小相关,也就是上文fontsize提到的AscenderDescender之间的高度,Ascender + Descender = conent-area的高度,以下图所示:

image.png

  1. 内联盒子(inline boxes):内联盒子不会让内容成块显示,而是排成一行。若是(文字)外部包含inline水平的标签(span、a、em、strong等),则属于内联盒子。若是是个光秃秃的文字,则属于匿名内联盒子。图示会更清楚,下图红色虚线框部分是匿名内联盒子,实线框部分是内联盒子:

image.png

  1. 行框盒子(line boxes):每一行就是一个行框盒子,每一个行框盒子又是由一个一个内联盒子组成。
  2. 包含盒子(containing box):标签所在的包含盒子是由一行一行的行框盒子组成。

具体的例子

咱们来考虑文本占据的高度,见下例:

image.png

p标签的高度从何而来呢,是由里面的文字撑开的吗?答案:不是的,实际上这个高度是由line-height决定的!再看下例:

image.png

经过此例说明,内联元素的高度是由行高决定的!

至此,咱们能够发现:

  1. 行高因为其继承性,影响无处不在,即便单行文本也不例外。
  2. 行高只是幕后黑手,高度的表现不是行高,而是内容区域行间距。也是就说,

内容区域高度(content area)+行间距(vertical spacing)=行高(line-height),其中行间距分上下部分,间距对半分。

注意:

  1. 内容区域(content area)高度只与字号(font-size)以及字体(font-size)有关,与line-height没有任何关系。
  2. simsun字体(即宋体)下,内容区域高度等于文字大小值。因此,在simsun字体下,font-size+行间距=line-height。行间距上下拆分,就有了半行间距;例如在simsun字体下,font-size=240pxline-height=360px,则半行间距是:(360-240)/2 = 60px

若是line-height 小于font-sizeinline box会优先于行高,以保证inline box的高度正好等于行高。例:font-size: 16px; line-height: 12px; inline box高度为12pxcontent area会溢出,inline box的顶部和底部半行高会折叠起来,以保证inline box的高度。图示以下:

image.png

对于行高,咱们得出如下结论:

一、行高 由 内容区域高度和行间距组成,行间距能够为负值,行间距分上下部分:上间距、下间距,它们距离相等。

二、行高用于计算 line-box 的高度

三、包含盒子的高度就是单行 line-box 高度的累加

属性值表现

行高支持如下种类型的属性值:

  • normal
  • 比例值,好比1.5
  • 具体长度值,好比1.5em
  • 百分比值,好比150%

一、normal

normal是默认属性值,与字体相关联,具体怎么关联呢,咱们使用FontForge软件打开Catamaran字体来看一下:

image.png

  • 常规的 Ascent/Descent:ascender770,descender230,用于渲染字符。
  • 规格 Ascent/Descent:ascender1100,descender540。用于计算 content-area 的高度
  • 规格 Line Gap:用于计算 line-height: normal

Catamaran 这款字体中,Line Gap 的值是 0,那么 line-height: normal 的结果就跟 content-area 的高度同样,是 1640 相对单位。

为了作对比,咱们再看看 Arial 字体,它的 em-square 是 2048ascender1854descender434line gap67。那么当 font-size: 100px 时,

  • content-area 的高度就是 100/2048*(1854+434) = 111.72,约为 112px
  • line-height: normal 的结果就是100/2048*(67+1854+434) 约为 115px

全部这些值都是由字体设计师设置的。

二、比例值

使用比例值做为行高值,例如line-height:1.5,这个比例值是相对当前元素的font-size来计算的, 假如font-size = 20px,那么line-height = 1.5*20px = 30px

三、具体长度值

使用具体长度值做为行高值,好比

  • line-height:1.5 rem/em(相对单位)
  • line-height:20px/pt(固定单位)

四、百分比值

使用百分比值做为行高值,好比 line-height:150%,这个百分比也是相对当前元素的font-size,因此假如fontSize = 20px,那么line-height = 1.5*20px = 30px

须要特别的注意的是,比例值和百分制从计算来看貌似没什么差异,可是最终效果是不同的,好比:

  • line-height:1.5,全部可继承元素会本身的font-size从新计算行高,能够理解为只是继承比例值。
  • line-height:150%,当前元素根据font-szie 计算行高后,会将这个值继承给下面的元素,能够理解为继承了具体的值。

举个例子 ,看下面一段HTML代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text /css"> div { line-height:1.5; font-size:24px; } p { font-size:60px; } </style>
</head>

<body>
    <div>
        <p>个人font-size
为60px~</p>
    </div>
</body>

</html>
复制代码

此时p标签的行高为:1.5×60 = 90px,两行行框盒子高度为180px

line-height:150%时,此时先计算 div 标签的行高:150%×24 = 36px ,而后继承给p标签,因此两行行框高度为72px

后语

经过对font-sizeline-height的讲解,相信你们都明天它们的含义了,回到前言提到的那个问题:line-height设置为父容器的高度,为什么能让文本垂直居中?我相信你们在阅读完这篇文章应该已经有答案了吧。

相关文章
相关标签/搜索