Web Fonts 的优化:Web Fonts 字体加载策略
特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)
字体加载优化策略
前面的篇幅告诉我们,使用 Web Fonts 会造成布局偏移,页面渲染时会发生重排和重绘。这会让页面在渲染时变得更慢,用户体验会更差。如果我们要对此进行优化,减少 Web Fonts 引起的布局偏移,就要从字体加载方面去做相应的优化策略。@Zach Leatherman 经过多年的研究,对字体加载提供了一些优化策略:
使用 font-display 来防止布局徧移
font-display
是 CSS Fonts Module Level 4 中规范中的一部分,主要用来告诉浏览器在不同的下载时间和可用时间下是如何渲染文本的。
不管是 FOIT 还是 FOUT (字体加载策略),两者都不太理想,会产生布局偏移。庆幸的是,在 @font-face
规则中添加 CSS 的 font-display
可以告诉浏览器我们更喜欢 Web Fonts 在不同的下载时间和可用时间下以哪种方式来渲染文本。
@font-face {
font-family: AlibabaSans102;
font-display: optional;
src:
url('/font/AlibabaSans102.woff2') format('woff2'),
url('/font/AlibabaSans102.woff') format('woff'),
url('/font/AlibabaSans102.ttf') format('truetype');
}
font-display
有五个可选值(auto
,swap
,block
, fallback
和 optional
),其中 auto
是它的默认值,也就是浏览器渲染 Web Fonts的默认行为(大多数浏览器喜欢 FOIT)。另外四个值在字体未加载完的前后,浏览器将会以不同的形式(Web Fonts 还是备用字体)渲染文本,即 修改 Web Font 的渲染行为。在开始介绍了解这几种类型之前先来了解一个基本概念:字体显示时间轴。
字体显示时间轴
字体显示时间线基于一个计时器,该计算器在用户代理(浏览器)尝试使用给定下载字体的那一刻开始。时间线分为三个时间段,在这三个时间段中指定使用字体的元素的渲染行为。
- 字体阻塞周期(Block):如果未加载字体,任何试图使用它的元素都必须渲染不可见的后备字体。如果在此期间字体已成功加载,则正常使用它
- 字体交换周期(Swap):在阻塞周期后立即发生,如果未加载字体,任何尝试使用它的元素都必须渲染后备字体。如果在此期间字体已成功加载,则正常使用它
- 字体失败周期(Fail):在交换周期后立即发生,如果在此周期开始时字体还未加载,则标记为加载失败,使用正常的后备字体。否则,字体就会正常使用
有了这个概念,我们开始来了解 font-display
取 swap
、block
、fallback
和 optional
会让浏览器以什么方式(字体显示时间轴)来渲染使用了 Web Fonts的文本。先从 swap
开始!
swap
font-display
取值为 swap
会告诉浏览器,Web Font在未加载完成之前都采用备用字体来显示文本(也就是 FOUT)。不管 Web Font 加载费时多久,只要字体被加载,文本就会从备用字体切换到 Web Font。使用 swap
方式的优势是可以让用户立即看到内容,但备用字体最好是能和 Web Font 相似,以防止字体交换(备用字体切换到 Web Font)时出现较大的布局偏移。
block
font-display
取值 block
则会告诉浏览器,Web Font 在未加裁之前隐藏文本(也就是 FOIT)。不过 block
并不会让使用 Web Font 的文本永远隐藏不可见:如果 Web Font 在一定时间内(通常是 3s
)未加载,文本不可见,但超过3s
这个时间,浏览器会使用备用字体渲染文本(介于 Web Font 加载时间大于 3s
与加载完成之间),一旦 Web Font 加载成功,就会从备用字体切换到 Web Font。
是否选择 block
就得看你自己的选择了。如果你说找不到和 Web Font 相似的备用字体,又不希望在字体切换时造成较大的布局偏移,你可以选择 block
,但你也得记住,使用 block
时有可能会有近 3s
的时间内用户什么也看不到(在这个时间段内文本被隐藏)。这有可能会让用户感觉访问的页面什么内容都没有,甚至会觉得加载页面失败。
fallback
font-display
的 fallback
和 swap
很相似,但有两点不同:
- 字体阻塞期非常的小,大约
100ms
,如上图所示,Web Font在小于100ms
未加载完,文本会不可见,一旦超过100ms
就会使用备用字体,使用备用字体渲染 - 如果 Web Fonts 在
3s
内没有加载,会一直使用备用字体渲染
即 Web Fonts 在小于 0.1s
未加载时,文本不可见(文本有0.1s
不可见期); 0.1s ~ 3s
内加载成功,则会在 0.1s ~ 3s
内使用备用字体渲染,字体一旦加载完就会切换到 Web Fonts 渲染,3s
内还未加载成功(即使在超过 3s
字体加载成功,比如 4s
时加载完成),文本也会一直使用备用字体渲染,好像是字体没加载成功一样。
如果你并不关心用户在第一次访问你的 Web 应用时是否看到你的 Web Fonts(很可能他们自己也不那么关心),那么 fallback
是一个不错的选择。
optional
optional
与 fallback
类似,但它给字体一个极短的时间(~100ms
)来加载,之后就不会被切换。从上图的字体显示时间轴上可以看出,如果 Web Fonts 在小于 0.1s
内未加载完成,即使在后面字体完成加载,文本也不会使用 Web Fonts 渲染。同样,它也有一个极短时间(~100ms
)会让文本不可见。
不过,它确实有一个额外的功能,即如果连接速度太慢,字体无法加载,它可以让浏览器中止字体的请求。
optional
对 Web 可用性有明显的好处,而且它对慢速的网络连接的数据占用也有改善。不过 optional
也有着自己独特之处。这样说吧,如果显示的是备用字体,那么 Web Fonts 将永远不会被显示,即使是快速的加载(除非在小于 100ms
字体加载完成)。因此,这就导致用户在快速的设备和连接上,文本使用备用字体渲染出来了,Web Fonts 已被加载,但它并没有被渲染出来。只有当用户浏览到另一个页面时,Web Fonts 才会被显示出来。
测试结果
上面是 font-display
属性几个值的使用规范。我们来看他们在 WebPageTest 中的表现。以 Telegraph 为例,连接速度提高到下载和上传为 .6Mbit/s
,而且 Web Fonts 资源是同源情况之下:
我们取几个重要数据:FP(First Paint,首次渲染)时间、带有不可见的占位符文本的页面布局时间、LCP(Largest Contentful Paint,最大内容的绘制)时间,Web Font的交换时间、差异(第一个交换的文本):
swap
:页面加载的8.1s
时绘制出了第一个像素,200ms
后,页面结构完成,备用字体被渲染;Web Fonts 最终在3.8s
后被交换。文字是可阅读的block
:页面加载的7.9s
后绘制出了第一个像素,200ms
后,页面结构看起来完整,但没有文字,直到3s
后,文字才渲染出来;然后在4.1s
后,Web Fonts 被换成了备用字体fallback
:页面加载的8.1s
时将第一个像素绘制到屏幕上,大约100ms
后,页面结构完成,但没有文字被渲染;大约在200ms
后,备用字体渲染出来,因为 Web Fonts 还需要3s
多的时间来加载,所以字体交互并没有发生(因为它已经超过了交换的截止点)。从用户角度来说,页面很稳定,可以阅读optional
:optional
是最简单的检查结果之一。页面在加载的7.7s
时绘制出了第一个像素,100ms
后,页面结构完成,备用字体被渲染。尽管 Web Fonts 正在后台下载,但在这个页面的生命周期内,它永远不会被显示。如果用户浏览到网站上另一个使用相同字体的页面,这时他们就会看到这个字体(因为,它现在存在于浏览器缓存中),但对于当前页面来说,这个字体不会被使用
简单小结一下
CSS 的 font-display
允许我们使用 auto
(浏览器默认行为)、swap
、block
、fallback
和 optional
等值修改浏览器对 Web Fonts 的渲染行为。在加载 Web Fonts 时,我们要防止布局偏移(可以使用 CWV 的 CLS 来计算 Web Fonts 引起的布局偏移)。这发生在两种情况之下:
- FOUT :备用字体被换成了Web Fonts ,例如
font-display: swap
- FOIT:文本不可见,直到 Web Fonts 加载成功被渲染,例如
font-display: block
浏览器目前有一个类似 block
的默认策略。不过,唯一能消除布局偏移的是 optional
,在结合字体其他加载策略下,optional
将是你最佳选择!
你的 Web 应用上的每一种字体都会有自己的 FOIT 或 FOUT —— 字体在加载时被单独交换(Swap),而不是在它们全部加载完成时交换。这可能会导致一些其他的问题,详见 @Mitt Romney 的 《Web Font Problem》。为了完全控制字体的加载,还需要借助 JavaScript 脚本或其他的一些字体加载策略!
加载更少的字体文件
加载一两个字体文件来渲染文本并不会(可能不会)对页面渲染速度产生巨大影响,但下载多个(比如五个,十个)字体文件对页面渲染速度会(较大可能)产生巨大影响!比如下面所示三个不同网站使用的 Web Fonts,以及页面加载字体时的瀑布流图:
从图上也可以略知,字体文件加载数量对页面渲染速度的影响吧!因此,我们应该在满足设计所需,确保你提供最小数量的字体文件,这也是确保浏览器在布局时有这些文件可用的最好方法,从而减少出现 FOUT 布局变化的可能性。让我们来看看在保持设计的同时加载更少字体文件的一些技术。
使用伪粗体和伪斜体
在 Web 中使用 伪粗体 (Faux Bold) 或 伪斜体 (Faux Italic) 可以会引起 FOFT (Flash Of Faux Text),即 伪文本闪现!设计师也很讨厌这种效果!
那么什么是伪粗体和伪斜体呢?很多时候,同一个字体通常会包括一堆不同的文件,比如下图中的 Avenir Next
字体就有十二种:
往往同一字体将九种字重(font-weight
的值可以是 100
、200
、300
、400
、500
、600
、700
、800
和 900
)与常规体和斜体的变体结合起来,就会产生 18
个独立的字体文件!
为此,你可能会使用 @font-face
加载很多个字体文件:
@font-face {
font-family: 'Lora';
src:
url('/font/Lora-Regular-webfont.woff2') format('woff2'),
url('/font/Lora-Regular-webfont.woff') format('woff'),
url('/font/Lora-Regular-webfont.ttf') format('truetype');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src:
url('/font/Lora-Italic-webfont.woff2') format('woff2'),
url('/font/Lora-Italic-webfont.woff') format('woff'),
url('/font/Lora-Italic-webfont.ttf') format('truetype');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src:
url('/font/Lora-Bold-webfont.woff2') format('woff2'),
url('/font/Lora-Bold-webfont.woff') format('woff'),
url('/font/Lora-Bold-webfont.ttf') format('truetype');
font-weight: bold;
font-style: normal;
font-display: swap;
}
前面我们说过,@font-face
引入的字体文件并不代表页面加载的时候就会下载相应的字体文件,只有满足一定条件才会被下载,比如说被引用了。不过,你可能会碰到只有一两个字或词会用到粗体或斜体的情景,为此引用了独立的粗体或斜体的字体文件。为了个别文字渲染成粗体或斜体,浏览器也会将整个字体文件下载。
事实上,浏览器可以自己制作 粗体 和 斜体 的字体,这被称为 伪粗体(Faux Bold) 和 伪斜体 (Faux Italic)。这也意味着你只需要加载一个常规字体文件即可(前提是设计师能接受 FOFT 的文本渲染现象)。
浏览器自己制作的粗体和斜体与设计师提供的字体可能存在一定的差异,比如:
对于某些字体,这种差异是很大的,尤其是那种很花哨的字体。我们可以通过删除 @font-face
声明来检查你的字体,除了常规的字体版本之外,其他字体都可以删除,然后截取渲染之后的效果图来做对比,就能轻易发现它们之间的差异。
另外,大多数标准西文字体都会包含粗体和斜体的变体,但许多新颖的字体(或 Web Fonts,对于 Web Fonts 取决于设计该字体的设计师)是不包括这些(粗体和斜体的变体)。比如,用于中文、日文、韩文或其他语标文字的字体往往不含这些变体,同时,从默认字体中生成,合成这些变体(即伪粗体或伪斜体)可能会妨碍文本的易读性。在这些情况之下,最好是关闭浏览器默认的 font-synthesis: none
字体合成特性。CSS 的 font-synthesis
特性可以控制浏览器全成哪些缺失的字体,粗体或斜体,该属性值可以是
如需转载,烦请注明出处:https://www.w3cplus.com/performance/optimizing-web-fonts-part3.html
如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!