Web Fonts 的优化:Web Fonts vs. 系统字体
特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)
Web Fonts 在 Web 中的使用已随处可见,比如聚划算页面中的 价格 使用的就是 Web Fonts(即 AlibabaSans102-Bd
):
虽然使用 Web Fonts 能在视觉上达到更好的效果(满足设计师的需求),但对于 Web 性能是有影响的,给用户的体验也是有影响的。如果Web Fonts 未加载,浏览器通常会延迟任何使用 Web Fonts 的文本(比如聚划算的价格)。这在许多情况下,将延迟 FCP(First Contenttful Paint),在某些情况下也会延迟 LCP(Largest Contentful Paint)。甚至更为严重的是导致布局偏移(Layout Shifts),会触发页面的重排和重绘(Web Fonts 和它的备用字体或系统字体在页面上占用不同的空间), 也会触发 CLS(Cumulative Layout Shift)。更令人感到头痛的是,Web Fonts 造成布移偏移的原因是 FOUT(Flashes Of Unstyled Text),而且 FOUT 还是业内公认的难以解决的。
简单地说,Web Fonts 对视觉效果是有显著帮助,但对Web性能和用户体验是有严重影响。如果在实际业务中能避免 Web Fonts 的使用应该尽可能的不用,如果实在不能避免,那就要在使用 Web Fonts时做一些策略上的选择。接下来,我们围绕着 Web Fonts 的使用和性能优化来展开讨论。
Web 排版
一直以来在 Web 上都是以 “内容为王”,其中文字内容在 Web 内容中占了很大的比例。即使是非装饰性的图片也应该在 HTML 的标记 <img>
中用文字来描述图片(alt
属性)。如果 Web 上的内容都是一段一段的文字,那么这个地方就会变得很无聊。
值得庆幸的是, Web 是一种视觉媒介,有许多机会通过 设计 和 排版 来传达思想。多年来,设计师们急于将自定义的排版带到 Web 上,并突破“Web安全字体”的限制。在 Web 近30年的发展过程中,先后使用过 “图片替换文本”(带有艺术字体,至今也还在使用),sIFR(Scalable Inman Flash Replacement,使用Flash等价物替换屏幕上的文本元素,今天基本废弃不使用),接下来是 cufón(2017年停止服务)。但这些技术都存在一定的缺陷,甚至已不是现代 Web 开发的主流技术,哪怕现在还在使用的 “图片替换文本” 也不建议使用。比如下图就是“图片替换文本”技术在Web页面中的运用场景:
在现代Web开发中,我们应该使用 CSS 的 @font-face
技术来使用自定义的字体(即 Web Fonts),该技术早在 2008 年左右就出现了(最早出现在 1998年 CSS2规范中),可以让浏览器加载本地字体或放在CDN的字体:
@font-face {
font-family: 'Alibaba Sans 102 v1 TaoBao';
src: url('AlibabaSans102v1TaoBao-Bold.eot');
src: url('AlibabaSans102v1TaoBao-Bold.eot?#iefix') format('embedded-opentype'),
url('AlibabaSans102v1TaoBao-Bold.woff2') format('woff2'),
url('AlibabaSans102v1TaoBao-Bold.woff') format('woff'),
url('AlibabaSans102v1TaoBao-Bold.svg#AlibabaSans102v1TaoBao-Bold') format('svg');
font-weight: bold;
font-style: normal;
font-display: swap;
}
CSS 的 @font-face
对于 Web 来说是一个很好的补充,它解决了上述老技术(“图片替代文本”、sIFR和cufón)中与可访问性和可维护性有关的许多问题。但是,@font-face
也带来了它自已一系列挑战。主要是不同的字体格式,以及它们的加载方式,更为麻烦的是它对Web性能和用户体验的影响。
**注意,Web安全字体(Web Safe Fonts)不等同于 Web字体(Web Fonts),其中 Web 安全字体指的是系统中(或客户端)都兼容(或大部分兼容)的字体(也是系统字体中一子集),而 Web 字体大多指的是自定义字体(具有个性化字体),也就是
@font-face
中引入(加载)的字体!
那我们就先从“系统字体与Web字体”开始聊起。
系统字体 vs. Web 字体
系统字体 是指安装在电脑上的字体,这些字体通常包含在操作系统中,但也可以与某些应用程序捆绑在一起或用户手动安装:
(上图是macOS Big Sur 系统中自带的字体和用户安装的字体,打开 Font Book APP 可查阅)
Web Fonts 一般是指存储在项目指定的目录(如 /src/assets/fonts/
)或网络服务器上的字体文件,浏览器客户端或Web应用程序临时下载这些文字是为了让 Web 页面按照设计师的意图渲染文字效果。比如 Google Fonts 和 Adobe Typekit 都是著名的 Web Fonts 服务商,提供很多在线 Web Fonts:
随着 2009 年 Adobe Typekit 等服务的推出,Web Fonts 就开始流行起来。在此之前,如果设计师和 Web 开发者希望他们的 Web 页面或应用上的文字在不同的浏览器和操作系统上看起来一样,就只能使用一些“网格安全”的系统字体,比如 Arial
、Calibri
、Helvetica
、Verdana
、Courier
、Georgia
、Palatino
和 Times New Roman
等:
(中间黄色区域是在Widows 11 和 Mac OS12 Monnterey 两系统中的Web安全字体)
十几年过去了,Web Fonts 大行其道,而系统字体则失宠,被许多人视为无聊和缺乏想象力。但是,Web Fonts并像 Google Fonts 总是免费的,有些Web Fonts是需要花钱购买的。另外, Web Fonts 的在Web上使用也是要附出一定代价的(除了购买要钱),还会占用用户的带宽,也给 Web开发者在性能优化上(比如字体加载)带来不小的压力,而且使用 Web Fonts 还有可能引起不同方式的文本闪现(比如 FOUT、FOIT 和 FOFT)。
使用系统字体的最大好处是,它们已经存在于大多数设备上。这意味着当用户访问你的 Web 应用时,被使用的字体不需要被下载到用户的电脑上。这为用户节省了带宽,降低了加载你的 Web应用所需的请求数。再强调一次,Web Fonts 则刚好相反,大多数情况之下(除使用 Base64 URI格式字体)都需要下载才能让 Web 应用上的文字按照指定的 Web Fonts 渲染。比如 Medium.com 首页,就有多个 Web Fonts 文件被下载:
在我们讨论选择正确的 Web Fonts以及如何确保它不影响你的 Web 应用的加载时间之前,我们首先需要问自己一个问题。真的需要使用定制的 Web Fonts 吗?还是使用系统字体就足够了?正如 @David Gilbertson 所说:
是否决定使用 Web Fonts,应该按“应该”或“不应该”这样一刀切的说法来决定,而是应该有某种准则来帮助你决定是否在自己的应用中使用 Web Fonts。
换句话说,是否使用 Web Fonts其底线是要问自己为什么需要使用一种 Web Fonts?尝试着按上面的规则去做选择,可能会比“应该”或“不应该”更明智。简而言之,如果 Web Fonts 给你带不任何的价值,我们应该以“系统字体优先”为原则,因为这也是一种更可持续的方法来选择字体。
系统字体的使用
众所周知,在 Web 开发中,都是通过 CSS 的 font-family
属性给文本指定一个字体或一个字体集来渲染文本,比如:
h1 {
font-family: fell, Georgia, Cambria, "Times New Roman", Times, serif;
}
h2 {
font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
p {
font-family: charter, Georgia, Cambria, "Times New Roman", Times, serif;
}
font-family
非常有意思,当该属性的值是一个系列值(Font Stacks)时,客户端首先会取这个系列值中的第一个字体,如果客户端(系统)没有这个字体,那将会取第二个,依此类推。如果 font-family
属性指定的字体集都不在系统中或未显式指定字体名称,那么将会取该属性的初始值,只是其初始值是依赖于用户代理(User Agent)。
在以往给 Web 应用显式设置系统字体的时候,都会指定具体的字体名称,比如:
// Windows, Mac, iOS
font-family: Georgia, Times, Times New Roman, serif;
font-family: Palatino, Palatino Lino