专栏名称: 前端早读课
我们关注前端,产品体验设计,更关注前端同行的成长。 每天清晨五点早读,四万+同行相伴成长。
目录
相关文章推荐
前端之巅  ·  80人小团队,限时任务!NYPL如何用Nex ... ·  6 天前  
程序员鱼皮  ·  教程老了,被吐槽了! ·  3 天前  
前端早读课  ·  【早阅】Better:一款AI代码审查工具 ·  3 天前  
大迁世界  ·  没人愿意使用这些数组方法 ·  1 周前  
大迁世界  ·  没人愿意使用这些数组方法 ·  1 周前  
51好读  ›  专栏  ›  前端早读课

【第3422期】字体性能优化终极指南

前端早读课  · 公众号  · 前端  · 2024-11-25 08:00

正文

前言

介绍了网页字体性能优化的各种策略和最佳实践。今日前端早读课文章由 @飘飘翻译分享。

正文从这开始~~

字体性能优化是一组网页开发技术,旨在使字体加载速度更快,渲染更平滑。这些技术诸如精心选择字体、使用高效字体格式、自托管、优化的 @font-face 声明、字体显示策略等实践。

【第3385期】你不知道的字体特点

优化网站显示的字体可以带来许多网页性能优势,包括更快的页面加载时间、更好的用户体验,以及在体验以及 Core Web Vitals 和其他性能指标的更好表现。

另一方面,提高字体性能往往以牺牲美学和创造力为代价(即需要小心使用自定义字体),这可能会使更难建立独特的品牌形象。

Web 安全字体 vs 网络字体:有什么区别?

在深入探讨字体性能优化的细节之前,让我们先简要了解一下字体术语中一个重要的方面 —— 网页安全字体与网络字体之间的区别。

两者都是数字字体文件,然而:

用户机器上安装了 Web 安全字体

Web 安全字体,通常被误认为是系统字体,但实际上它是预安装在大多数操作系统中的。因此,浏览器不必从网络下载字体文件和相关 CSS,这可以提高页面加载速度和其他网页性能指标,如 LCP 和 INP。

系统字体是 Web 安全字体的一个子集,它们由操作系统用于在本地应用程序中显示 UI 元素。如果你在你的网站上显示系统字体(我们稍后会看到如何操作),就可以为用户提供熟悉的操作界面。

使用 Web 安全字体的主要缺点是,其中许多字体看起来很普通,并且容易过度使用。为了为你的网站创建更具记忆性和独特性的外观,您可能想要使用自定义 Web 字体。

网络字体需要从互联网下载

网络字体是定制字体,大多数网页用户的操作系统上没有安装这些字体,因此浏览器需要下载字体文件和相关的 CSS 文件。它们可以托管在第三方域名上,例如 Google 的 CDN,也可以在自己的域名上自行自托管。

加载网络字体比 Web 安全字体需要更长的时间,因为它们需要从互联网下载。然而,通过实施各种性能优化技术,仍然可以将网络字体的速度提升到一个可接受的水平(我们将在下面看到它们)。

【早阅】内置语法高亮显示的字体

需要注意的是,虽然网络字体可以提升网站的外观和感觉,但定制字体设计需要相当好的设计技巧。如果没有必要的专业知识,你的字体选择可能不会那么成功,你的网站可能会看起来比使用看起来更通用的安全字体还要糟糕。

如果自定义字体并不那么重要,请使用 Web 安全字体。

从性能角度来说,在网站上只使用 Web 安全字体是最佳选择。接下来,我们将了解浏览器在不同场景下加载本地字体的方式,以及如何在使用本地可用字体时仍能拥有一定的设计自由度。

如果你没有定义字体家族会发生什么?

如果你在 CSS 中没有定义任何字体家族,浏览器将使用用户的字体设置中的默认字体。例如,在 Google Chrome 中,可以在 chrome://settings/fonts 管理员页面找到默认浏览器字体(也称为标准字体):

如果只使用通用字体名称时会发生什么?

CSS 字体模块第 4 级网页标准允许你将五个通用字体名称类型作为 font-family 属性的值使用,每种字体都有一组预定义的特性,用来精确定义,参见文档:

  • serif

  • sans-serif

  • monospace

  • cursive

  • fantasy

例如,你可以使用以下 CSS 规则来加载本地可用的衬线字体:

 body {
font-family: serif;
}

通用字体名称在不同的平台上可能对应不同的字体(这取决于许多因素,例如浏览器类型和版本、操作系统、本地可用的字体、用户偏好、网站使用的 Unicode 范围等)。还可能出现不同通用字体名称对应同一种字体的情况(例如,在 Windows 10 的 Firefox 中, sans-serif 和 fantasy 都映射到 Arial)。

以下是 Chrome 浏览器在 Windows 10 系统上使用五种通用字体渲染相同文本的示例(如果您想查看自己平台上使用的通用字体,可以在不同浏览器中打开该演示或下载源代码):

总的来说,如果你只在 font-family 声明中使用通用字体名称,那么你的网站将在不同平台上显示的字体看起来会有些相似,但对于所有用户来说,其美学效果并不完全相同。

如何添加 Web 安全字体栈?

字体栈是一个定义一个或多个备用字体的字体列表。浏览器会加载列表中第一个可用的字体,该字体可以从网络或用户设备上获取。CSS 允许您以以下方式将字体堆栈(而不是单个字体)分配给 font-family 属性:

 div {
font-family: Arial, Verdana, sans-serif;
}

如果你想要对网页字体有更多的控制权,但又不想下载定制的网页字体,你可以指定一个 Web 安全字体堆叠,通常它的外观比默认的字体映射更加独特。由于同一操作系统的用户通常在他们的机器上预装了相同的字体,因此使用相同操作系统的网站访客更有可能看到相同的字体。

你可以手动检查你要支持的操作系统中字体的可用性,或者您可以使用 CSSFontStack 集合中为 Windows 和 Mac 系统提供的预制作 font-family 声明中的 web-safe 字体集。

在创建一个适用于所有浏览器的字体集时,首先选择您希望作为默认字体的主字体,然后添加与之相似的备用字体,直到覆盖了您想要支持的所有操作系统,最后以最匹配的通用字体名称结束声明。

例如,CSSFontStack 为 Book Antiqua 字体推荐了以下 font-family 规则(请注意,所有备用字体也都是万维网安全字体):

 body {
font-family: Book Antiqua, Palatino, Palatino Linotype, Palatino LT STD, Georgia,
serif;
}

如何在每个操作系统上加载系统字体?

正如我之前提到的,在网站上加载系统字体会给你的用户带来一种熟悉感,这可以改善某些类型页面的用户体验,例如,在网络应用的仪表板上。

下面的 font-family 规则包含 Mac、Windows 和 Linux 操作系统的系统字体,并且它(或其相近变体)被像 GitHub 这样的流行网络应用程序所使用。

 body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
}

作为替代方案,可以使用 system-ui 值,它在用户的操作系统上加载系统字体,并被所有现代浏览器支持。

 body {
font-family: system-ui;
}

如果你想使用网络字体,不要加载超过两种字体家族

如果自定义字体对你的品牌设计至关重要,并且你决定在网站上使用网络字体,那么一般来说,不要在一页上使用超过两种网络字体,因为这可能会带来负面的性能影响,比如页面加载速度变慢、页面重量增加等。

例如,下面的页面(查看实时版本)下载了五个自定义字体家族 —— 正如您所见,由 DebugBear 生成的请求瀑布流显示,页面渲染被阻塞,直到所有五个字体文件都被下载:

此外,当备选字体与自定义字体交换时,可能会发生意外的布局偏移,这可能会损害你的累积布局偏移结果。要测试以下示例,请打开我们的免费网站速度测试工具,并对 https://www.annalytic.com/demos/multiple-web-fonts-test/ URL 进行测试

自托管网络字体

你可以通过将网页字体托管在自己的域名下(即自托管)来加快网页加载速度。

要自托管任何网络字体,你需要:

  • 将字体文件上传到您的服务器

  • 在 CSS 中添加相关的 @font-face 声明(下面,我们将看到如何优化它们)

自托管网络字体的网络性能优势源自以下几个因素:

  • 你不必连接一个或多个第三方服务器(例如,下载 Google 字体时,需要进行两次外部连接,一个用于字体文件,另一个用于 CSS),这减少了首次字节时间(TTFB)。

  • 你可以优化您的 @font-face 声明(我们稍后会看到如何进行优化)。

  • 因为字体是静态资产,你可以从全球分布的内容分发网络(CDN)下载它们,这样可以降低了延迟(如今,大多数 CDN 允许你使用自己的域名)。

自托管网页字体的另一个优势是隐私,因为你的访客的 IP 地址不会与第三方共享。

虽然在过去,自己托管网页字体并不被普遍推荐(即对于那些无法访问高速服务器或 CDN 的网站),但现在情况已经不再如此。HTTP Archive 的《Web Almanac 2022》提到:“在引入缓存分区后,使用托管服务不再有性能优势”,这意味着现在普遍推荐自托管网页字体。

尽管自托管网页字体在性能有优势,但由于许可限制,这可能并非总是可行的选择。例如,Adobe Fonts 就是这种情况;尽管仍然有一些解决方案,特别是如果你愿意付费的话。

如何自托管 Adobe 字体

官方无法下载和自托管 Adobe Fonts—— 有趣的是,他们的 ' 字体授权 ' 页面以网页性能为由解释了这一点,称他们的内容分发网络 " 在静态资产方面比本地托管表现得更好、更可扩展”(未提供证据)。

然而,这一声明与事实相悖,因为如果你通过 Adobe Originals 计划购买许可证(由 Type Network 等零售商销售),仍然可以自行托管一些 Adobe 字体。此外,Adobe Fonts 在 GitHub 上提供了一些开源字体,你可以在下载字体文件并添加相关 @font-face 规则到你的 CSS 后自行托管。

Adobe 字体还包含了第三方提供商(称为字型工坊)的字体。如果第三方提供商在其许可条款允许的情况下,你可以自行托管这些字体。

例如,Google 字体在 Adobe 字体中维护了一个字型工坊,提供了 408 种字体供 Adobe 用户使用,所有这些都使用开源许可,因此如果您从 Google 的网络下载它们,你可以自行托管它们。例如,Baloo Bhaina 2 字体可以从 Adobe 字体和 Google 字体以及其他几个地方获取,比如作为 npm 包发布,因为它是按照 SIL Open Font License 发布的。

如何自托管 Google 字体

将自托管 Google 字体添加到网站的最简单方法是使用 Mario Ranftl 创建的 Google Web Fonts Helper 工具,该工具生成所有必要的 @font-face 规则,以及将字体文件转换为 WOFF2 格式(我们将在下面详细探讨 WOFF2)。

Google Web 字体助手可以让你仅下载你需要在网站上使用的字体样式和字符集:

你也可以复制属于你的 @font-face 规则,这些规则你需要添加到你的 CSS 中。

在页面底部,您可以下载字体文件的 ZIP 压缩包 - 下载完成后,您需要解压缩它,并将字体文件上传到您的服务器上:

将自托管的 Web 字体转换为 WOFF2 格式

目前,WOFF2(Web 开放字体格式,版本 2)是最高效的字体压缩格式,其平均压缩比比 WOFF1 高出 26.61%,因为它使用了 Brotli 压缩(而 WOFF1 使用的是 GZIP,这是一个效率较低的压缩算法 —— 请比较 GZIP 与 Brotli 之间的差异)。

尽管 WOFF2 格式如今被广泛使用,但还是经常出现只能下载到性能较弱的字体格式的情况,如 TTF、EOT、OTF 或 WOFF1 的情况。例如,如果你从官方 fonts.google.com 网站下载 Google 字体,字体文件仍然以 TTF(TrueType Font)格式下载。

WOFF2 格式得到所有现代浏览器支持,这意味着你只需要将你的字体文件以 WOFF2 格式托管,正如《Web Almanac 2022》所说,“其他一切都可以抛之脑后”(指的是过去开发者需要为不同浏览器提供不同格式的自托管字体)。

将你的字体文件转换为 .woff2 格式,你可以使用转换工具,例如 CloudConvert 的 WOFF2 转换器。或者,如果你使用上述的 Google Web Fonts Helper,你将默认下载 WOFF2 格式的字体文件。

优化核心 Web 性能指标的 @font-face 声明

当你在网站上自行托管网络字体时,需要为每个字体文件在 CSS 中添加一个 @font-face 声明,该声明定义了字体的名称、位置和其他特性。

@font-face 属性有必需和可选描述符 —— 前者定义字体的名称和 URL,而后者则允许您指定字体的字符集、加载方式、大小和其他特性。

@font-face 声明所需描述符

要定义自定义字体,你需要按照以下方式在 @font-face 声明中添加 font-family 和 src 描述符:

 @font-face {
font-family: "Anonymous Pro";
src: url("fonts/anonymous-pro-v21-latin-regular.woff2") format("woff2");
}

需要注意的是,如果你使用了多种字体样式,每份文件都需要添加一个 @font-face 声明。

如果你想同时下载常规和斜体两种样式的 “匿名” 字体家族,这里有一个例子:正如您所见,我们还添加了 font-style 和 font-weight 描述符,以指定支持的字重和样式值:

 @font-face {
font-family: "Anonymous Pro";
font-style: normal;
font-weight: 400;
src: url("/fonts/anonymous-pro-v21-latin-regular.woff2") format("woff2");
}

@font-face {
font-family: "Anonymous Pro";
font-style: italic;
font-weight: 400;
src: url("../fonts/anonymous-pro-v21-latin-italic.woff2") format("woff2");
}

何时下载网络字体?

关于 @font-face 声明对性能影响的重要一点是,它们不会向服务器发送下载请求。

只有在页面上使用时,网页字体才会下载。

例如,如果你将 Anonymous Pro 字体分配给  标签的 font-family 属性,则浏览器只会在开始渲染  元素(而不是解析 @font-face 声明时)之前发送相应的 HTTP 请求给服务器。

 body {
font-family: "Anonymous Pro", monospace;
}

上述 font-family 规则只会下载常规字体文件 (anonymous-pro-v21-latin-regular.woff2),而不会下载斜体字体文件。

另一方面,下面代码只会下载斜体字体文件( anonymous-pro-v21-latin-italic.woff2 ),而不会下载常规字体文件:

 body {
font-family: "Anonymous Pro", monospace;
font-style: italic;
}

这是从 Chrome 开发者工具的网络标签页获取的证据(显示了后一个示例 —— 如你所见,常规字体文件并未下载):

如果你想让两个字体文件都下载,你需要在 CSS 中引用它们,例如:

 body {
font-family: "Anonymous Pro", monospace;
}
h1 {
font-style: italic;
}

可选描述符,用于提升字体性能

下面是 @font-face 声明的几个可选描述符,可以帮助您提升字体性能。接下来,我们将逐一详细介绍它们:

  • unicode-range

    • 只有当页面上使用了指定的字符时,才会下载字体文件。

    • FCP,LCP

  • local()

    • 检查用户是否已在本地安装了该字体,如果是,则加载本地版本而不是从网络下载字体文件。

    • TTFB, FCP, LCP

  • font-display

    • 定义了浏览器将使用的备用策略。

    • CLS

  • size-adjust

    • 调整主字体和备选字体的大小

    • CLS

unicode-range 描述符

unicode-range 描述符允许你从特定字体文件中选择要使用的字符。如果 HTML 不包含 unicode-range 定义的任何字符,则字体文件将不会下载。

你可以使用以下 CSS 代码来测试这种行为(下方的 unicode-range 描述符定义了一个单一的 Unicode 字符,即笑脸表情 —— 除非你在  标签内部包含一个笑脸表情,否则自定义字体将不会下载,而是使用通用的 monospace 备用字体):

 @font-face {
font-family: "Anonymous Pro";
font-style: italic;
font-weight: 400;
unicode-range: U+1F642; /* smiling emoji */
src: url("/fonts/anonymous-pro-v21-latin-italic.woff2") format("woff2");
}
body {
font-family: "Anonymous Pro", monospace;
font-style: italic;
}

有几个方法可以定义 unicode-range 描述符,例如可以使用多个 Unicode 值、通配符范围等(有关语法的详细信息,请参阅文档)。

字体子集的两个方向

代码示例中使用的 unicode-range 描述符是字体子集的一个实现方式:你已经生成了 WOFF2 字体文件并上传到了服务器,但只有在页面上使用了指定的 Unicode 字符时,浏览器才会下载该字体文件。

不过,你也可以对字体文件本身进行子集化。例如,当你在 Google Web Fonts Helper 中选择字符集时,它会生成一个只包含所选字符集的字符的子集化字体文件。

举个例子,如果您选择 Anonymous Pro 字体的希腊语和拉丁语字符集,您将下载一个名为 anonymous-pro-v21-greek_latin-regular.woff2 的文件,该文件仅包含希腊语和常规拉丁语字符(不包括西里尔字母和扩展拉丁字母)。

你可以通过创建只包含网站使用的字符的子集字体文件来进一步提高网页性能(例如,仅用于标志的显示字体,这是一个不错的解决方案)。要创建自定义的子集字体文件,您可以使用 Peter Müller 创建的工具 subfont。

需要注意的是,有些字体许可不允许子集化。不过,大多数 Google 字体使用的 SIL 开源字体许可,它支持这一操作 —— 你可以在 Jeff Frankl 建立的 subsetting.xyz 网站上检查其他字体许可。

local () 函数

local() 函数是所需 src 描述符的可选值 @font-face 声明。它允许检查字体是否已安装在用户的机器上,以便浏览器可以使用本地字体文件,而不是从网络上下载。

由于 src 描述符可以取多个值,你可以这样组合 local() 和 url() 函数:

 @font-face {
font-family: "Anonymous Pro";
font-style: normal;
font-weight: 400;
src: local("Anonymous Pro Regular"),
/* Full name */ local("AnonymousPro-Regular"), /* PostScript name */
url("/fonts/anonymous-pro-v21-latin-regular.woff2") format("woff2");
}

local() 声明必须在 url() 函数之前,因为如果浏览器找到本地文件,它就不会发送请求去下载在线文件。此外,最好同时提供字体文件的完整名称和 PostScript 名称(PostScript 是 Adobe 程序使用的页面描述语言,还可以在用户的机器上安装字体)。

如果你不确定某个字体的本地名称,可以使用字体查看工具,例如 Viktor Nübel 创作的 FontDrop! 应用,来检查字体命名表中的 fullName 和 postScriptName 值:

font-display 描述符

font-display 描述符允许你从四种预定义的字体显示策略进行选择,以指定用户在浏览器下载 Web 字体之前看到的文本样式。

很遗憾,现有的字体显示策略都不是完美的,因此你将在一定程度上牺牲性能或美观(或者两者都牺牲,但程度较小)。

使用网络字体,你基本上可以选择三种显示问题:

  • FOIT(闪现的不可见文本)– 浏览器会先显示不可见的文本,直到下载完网页字体。

  • FOUT(闪烁的无样式文本) – 浏览器会先使用备用字体渲染文本块,直到下载完网页字体。

  • 网络字体无法显示 - 如果网页字体未能及时加载(采用这种策略时,浏览器通常会根据用户的网络连接预先计算下载时间,甚至不会请求网页字体),浏览器将始终显示备用字体。

FOIT 和 FOUT 都可能导致意想不到的布局偏移(可以通过匹配网页字体和备用字体的大小来解决这个问题;稍后我们会介绍如何实现)。

字体显示描述符可以取以下值,每种值代表不同的字体显示策略(每种策略有两个阶段:字体渲染过程暂停的块阶段和备用字体替换网络字体的交换阶段):

  • block

    • 时间周期:短(根据 CSS 字体模块标准,浏览器供应商建议为 3s)

    • 交换周期:无限

    • 优点:将使用自定义字体(用户很可能不会看到备用字体,因为三秒是一个相当长的区块周期)。

    • 缺点:可能会导致字体外排和意外的布局偏移(使用备用字体来计算不可见文本的大小)

    • 推荐使用场景:如果自定义字体很重要,或者用于较短的文本串(例如用于标志的显示字体)或折叠以下的文本块。

  • swap

    • 时间周期:极短(推荐 100ms 或更少)

    • 换代周期:无限

    • 优点:文本将在备用字体中提前渲染,然后使用自定义字体。

    • 缺点:可能会导致 FOUT(帧外对象)和意想不到的布局变化。

    • 推荐使用场景:如果自定义字体很重要,并且需要较长的文本块。

  • optional

    • 时间周期:极短(推荐 100ms 或更少)

    • 换班周期:0

    • 优点:文本将在网页字体或备用字体中较早地进行渲染,既不会出现 FOUT(字体下载完成前的文本缺失),也不会出现 FOIT(字体下载完成后的文本缺失),不会导致页面布局出现意想不到的变动。

    • 缺点:如果自定义字体的加载时间超过 100 毫秒,则不会被使用。

    • 推荐使用:如果性能是首要考虑因素,并且自定义排版不是那么重要,那么建议使用较长的测试块(例如,  文本)。

  • fallback

    • 时间周期:极短(推荐 100ms 或更少)

    • 换档周期:短(推荐 3s)

    • 优点:自定义字体有三秒钟的加载时间(相比之下,可选字体的加载时间只有 100 毫秒),因此更有可能显示出来。

    • 缺点:可能会导致 FOUT(帧外输出)和意想不到的布局变化(但比交换策略的可能性要小)。

    • 推荐使用:如果需要自定义排版风格并且对美观性要求较高,那么建议使用此选项,因为它能够在美观性和性能之间找到平衡(例如,用于较长的测试块(如  文本))。

  • auto

    • 时间周期:无法提供

    • 换货期:不可用

    • 优点:无

    • 缺点:无

    • 推荐使用:这是 font-display 的默认值;它使用浏览器内置的显示策略,通常与块级显示策略相同。

为了获得良好的累积布局偏移结果,请对于较长文本块使用以下方式的 optional 或 fallback 策略:

 @font-face {
font-display: optional;
font-family: "Anonymous Pro";
font-style: normal;
font-weight: 400;
src: local("Anonymous Pro Regular"), local("AnonymousPro-Regular"),
url("/fonts/anonymous-pro-v21-latin-regular.woff2") format("woff2");
}

想要了解更多关于不同字体显示策略的工作原理,请查看我们的文章,了解如何解决由网页字体引起的布局偏移问题。https://www.debugbear.com/blog/web-font-layout-shift

size-adjust 描述符

size-adjust 描述符是 @font-face 声明中的一个较新添加项,但其浏览器支持已经相当好(所有现代浏览器的较新版本均支持)。它允许你匹配网络和备用字体的大小,以防止在切换期间出现意想不到的布局变化。

尺寸调整非常重要,因为不同字体的字符通常具有略微不同的宽度和高度,因此较大的文本块将在屏幕上占据不同的区域,当字体切换时可能会导致意想不到的布局变化。

size-adjust 描述符用于指定一个百分比值,用于定义将放大或缩小字体轮廓的倍数。你可以手动计算倍数,通过比较 Web 字体和备用字体的精确大小,或者使用 Brian Louis Ramirez 创建的 Fallback Font Generator 等工具。

下面,你可以看到如何调整 Anonymous Pro 网页字体和 Courier New 备用字体的大小。

首先,将 size-adjust 设置为 100%(其默认值),并检查这两个字体是否占用相同的空间(你需要比较文本块周围的矩形,因为需要调整这些矩形以避免意外的布局偏移):

如上图所见,自定义字体(绿色)比备用字体(黄色)稍小一些,因此我将 size-adjust 的值值增大,直到两个矩形占据相同的空间。

尺寸匹配度为 113%(建议您使用较短和较长的文本字符串测试 size-adjust 的值):

因此,带有 size-adjust 描述符的 @font-face 声明(在  标签中,我们还需要为 size-adjust 确工作而定义备用字体的顺序)如下所示:

 @font-face {
font-display: fallback;
font-family: "Anonymous Pro";
font-style: normal;
font-weight: 400;
size-adjust: 113%;
src: local("Anonymous Pro Regular"), local("AnonymousPro-Regular"),
url("/fonts/anonymous-pro-v21-latin-regular.woff2") format("woff2");
}

body {
font-family: "Anonymous Pro", "Courier New", monospace;
}

@font-face 声明还包含三个其他可选描述符,可以帮助你精确调整网页和备用字体的大小。

虽然你可以在不使用 Web 字体的情况下优化 CLS,但如果您希望提供更平滑的切换期,也可以考虑使用它们(所有字体均可在上述备用字体生成工具中找到,但请注意,截至撰写本文时,Safari 浏览器尚未支持任何字体):

  • ascent-override:指定了该字符相对于基线的高度将增加或减少的百分比值。

  • descent-override:指定了该字符的基线以下的字符高度将增加或减少的百分比值。

  • line-gap-override:指定了线条间距将增加或减少的百分比值。

在页面的头部区域插入 @font-face 规则

为了让字体下载尽可能快,将你的 @font-face 规则作为关键 CSS 的一部分,嵌入 HTML 页面的  部分。

有两件事情要牢记:

  • 如果在一个页面上存在多个 @font-face 声明,请从最重要的那个开始,这样它就会被首先请求(例如,用于  标签的自定义字体)。

  • 正如我之前所说,@font-face 声明不会向服务器发送请求。要启动下载过程,你需要通过定义一个 font-family 规则来在页面上引用字体。

这是一个包含内联并经过压缩的 @font-face 声明的代码示例,以及添加到  标签的一个 font-family 规则,该规则将启动 HTTP 请求(代码使用 Minifier.org 进行压缩):

 <style>
@font-face {
font-display: optional;
font-family: "Anonymous Pro";
font-style: normal;
font-weight: 400;
size-adjust: 113%;
src: local("Anonymous Pro Regular"), local("AnonymousPro-Regular"),
url(/fonts/anonymous-pro-v21-latin-regular.woff2) format("woff2");
}
body {
font-family: "Anonymous Pro", "Courier New", monospace;
}
style>

如果你无法自行托管网页字体,请优化下载速度

虽然自行托管自定义字体是推荐的方法,但在某些情况下,可能由于某种原因你无法这样做。

接下来,我们将看看如果你需要从谷歌或 Adobe 的 CDN 下载网页字体,如何仍然可以提升网页性能。

如果你无法自托管字体,如何优化谷歌字体的网页性能?

如果你从谷歌的 CDN 下载字体而不是自行托管,谷歌会为你提供一些优化字体性能和核心网页指标的选项。

在深入研究它们之前,让我们先来看看默认设置:

当你从谷歌的 CDN 下载网页字体时会发生什么?

这是 Google Fonts 提供的默认代码,如果您想从 Google 的 CDN 下载 Anonymous Pro 字体的常规和斜体样式,需要将其添加到 HTML 页面的  部分:

 <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:ital@0;1&display=swap"
rel="stylesheet"
/>

上面的代码下载了两个 WOFF2 文件(一个用于正常样式,另一个用于斜体样式)以及一个包含八个 @font-face 规则的 CSS 文件 —— 用于 Anonymous Pro 字体支持的四种字符集(西里尔文、希腊文、拉丁扩展和拉丁文)的正常和斜体样式(如果您还想要下载粗体和粗体斜体样式,CSS 文件中将包含 16 个 *@font-face* 规则)。

这是一大段代码,尤其是如果你只想使用拉丁字符集的时候。

你如何优化网页字体下载?

目前,没有方法可以删除您不想使用的字符集的 @font-face 规则(除非您使用 *text* URL 参数 - 见下文),因此 “最佳” 解决方案是仅请求您确实需要的样式(例如,如果您不需要粗体斜体,则从 URL 中省略它)。

你从谷歌 CDN 下载的 WOFF2 字体文件会自动优化,以适应支持 unicode-range 描述符的现代浏览器。这是因为 WOFF2 文件会检测页面上需要哪些字符集,并仅请求这些字符集的子集(例如,如果您的页面上没有希腊语或西里尔字符,您的 WOFF2 文件将不会包含这些字符)。过去,这是通过 subset 参数实现的,除非您需要支持遗留浏览器,否则现在不再需要使用该参数。

由于 subset 在现代浏览器中被忽略,因此,今天我们只能通过两个可选的 URL 参数来提升网页性能:

  • display:这是与上述 @font-face 声明中的 font-display 描述符等效的。默认情况下,Google Fonts 使用 display=swap ,但你可以将其更改为 display=fallback 或 display=optional 以改善您的累积布局偏移结果。

  • text:它通过仅包含指定文本中出现的字符来进一步细分字体(例如, text=YourBrand )。

例如,下面的  元素使用了 fallback 显示策略,仅下载了包含在 "YourBrand" 文本中的字符:

 <link
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:ital@0;1&text=YourBrand&display=fallback"
rel="stylesheet"
/>

这是经过子集处理的 WOFF2 文件的外观(在上述 FontDrop! 应用程序中打开)—— 正如您所看到的,它只包含我们请求的字符(它甚至可以区分大写和小写字母):

有趣的是,如果你使用 text 参数,下载的 CSS 文件只会包含两个 @font-face 声明,这些声明定义了请求的字符集(在此情况下,是拉丁字符集的常规和斜体样式)所对应的字符集:

现在,你可能会问,是否将所有拉丁字符都分配给 text 参数是一个好主意,以防止 Google API 添加所有不必要的 @font-face 声明。

从技术上来说这是可行的,在这种情况下,CSS 文件只会包含两个 @font-face 声明。

然而,URL 参数只接受字母数字字符,因此你无法添加额外的字符,如引号或感叹号(如果你这样做,浏览器会忽略它们)。因此,如果页面上有这样的字符(这是非常可能的),浏览器将使用备用字体加载它们。结果是,你的文本块看起来会 “有点” 奇怪,而且浏览器还需要加载网页和备用字体。

因此,总的来说,不建议这样做(可能也不会带来显著的性能提升)。如果你仍然想这样做,以下是你需要使用的代码:

 <link
href="https://fonts.googleapis.com/css2?family=Anonymous+Pro:ital@0;1&text=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&display=fallback"
rel="stylesheet"
/>

预连接链接是如何加快字体渲染速度的?

当你从 Google 的 CDNs 下载 Google 字体时,你需要添加的其他两个  元素是两个预连接链接 —— 第一个预连接到 CSS 文件的 fonts.googleapis.com 子域,第二个预连接到 fonts.gstatic.com 以获取 WOFF2 文件:

 <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />

预连接是一种资源提示类型,允许你在页面渲染过程中较早与第三方域建立 HTTP 连接,以便在需要资源(例如字体)时立即使用该连接。通过预先连接到 Google 的 CDN,可以使字体加载更快。

如上所示,第二个  标签也包含一个 crossorigin 属性,这是必要的,因为字体文件必须通过 CORS 连接请求。

预加载谷歌字体是一个好主意吗?

为了进一步加快字体渲染速度,你可以考虑在预连接到服务器后预加载最重要的字体文件。预加载是另一种资源提示类型,允许你下载资源文件。

预加载网络字体是一个颇具争议的话题,因为有时开发人员会过度操作,例如,在一个页面上预加载 10 个不同的字体文件。谷歌的 web.dev 文档也警告不要预加载太多网络字体,因为这会 “从加载其他资源中占用浏览器资源”。

然而,根据我们的经验,预加载一到两个字体文件(你在页面上使用最多的那些)可以帮助减少页面加载时间。

例如,预加载用于  文本和标题的字体文件是一个好主意。以下代码片段预加载了 Anonymous Pro 字体的常规和粗体样式(您需要在预连接提示下方的  部分添加它):

 
<link
rel="preload"
href="https://fonts.gstatic.com/s/anonymouspro/v21/rP2Bp2a15UIB7Un-bOeISG3pHls29Q.woff2"
as="font"
type="font/woff2"
crossorigin
/>



<link
rel="preload"
href="https://fonts.gstatic.com/s/anonymouspro/v21/rP2cp2a15UIB7Un-bOeISG3pFuAT4C7c7Q.woff2"
as="font"
type="font/woff2"
crossorigin
/>

要获取 WOFF2 文件的 URL,打开您的 DevTools 的网络标签页,加载你的网站,找到文件列表中的字体,并从头部标签页复制 URL:

如果你无法自托管字体,如何优化 Adobe 字体以提升网页性能?

要将 Adobe Fonts 添加到你的网站中,你需要在 Adobe Fonts 网站上创建一个网页项目。

以下是 Adobe 提供的指南,可帮助您优化 Adobe Fonts 在 Web 项目中的核心性能指标和其他性能指标:

  • 自定义你的字体显示策略

  • 选择所需的字符集,然后使用动态子集选择

建议你按照以下方式预先连接 Adobe 的服务器:

 <link rel="preconnect" href="https://use.typekit.net" crossorigin />
<link rel="preconnect" href="https://p.typekit.net" crossorigin />

如果你的 Adobe 字体仅从一个服务器下载( use.typekit.net 是旧服务的子域,而 p.typekit.net 是 Adobe 的新网络字体服务的子域),只需添加相应的预连接提示(你可以在浏览器的开发者工具或我们的 DebugBear 应用程序中查看)。

类似于 Google 字体,在预连接字体服务器后预加载最重要的字体文件也是一个不错的主意(您可以使用前面讨论的代码片段;只需更改 URL 即可)。

实施通用的网页性能优化最佳实践

优化网站的字体,包括在性能和美学之间找到合适的平衡,对于为访客提供良好的用户体验至关重要。这是必不可少的,但还不够。

为了向用户提供快速加载的字体,我们建议你实施以下一项或多项网页性能最佳实践:

  • 为你的 CSS 文件使用代码拆分技术,并移除无用的 CSS,因为这些技术可以减少页面上下载的字体数量(因为字体文件需要在 CSS 代码中被引用才能启动 HTTP 请求)。

  • 支持 HTTP/3 网络协议,因为它可以实现更快的下载速度。

  • 从 CDN 下载您的静态资源,包括字体。

  • 实现缓存 - 这通常由您的网站主机或 CDN 提供商自动完成,但如果您需要手动处理,请使用长期过期缓存头为字体文件。

关于本文
译者:@飘飘
作者:@Anna Monus
原文:https://www.debugbear.com/blog/website-font-performance

这期前端早读课
对你有帮助,帮” 
 “一下,
期待下一期,帮”
 在看” 一下 。