高级 Web 字体优化技术

2025-06-07

高级 Web 字体优化技术

图片描述

网站开发者使用自定义字体由来已久。由于自定义字体不存在于操作系统中,它们需要随网站加载,因此需要快速加载并跨平台一致地显示。常见的例子包括 Google Web Fonts——一个采用 Web 开放字体格式 (WOFF2) 的专用 Web 优化字体库,它提供出色的压缩性能,以最大限度地减少字体大小。

然而,实际上,Google Web 字体通常只有 20-30KB。如果将其乘以几种不同的样式和粗细,您的网站很快就会达到 100-150KB。自定义字体的另一个缺点是,它们会在页面加载过程中导致明显的布局偏移。

本文分享了使用 Web 字体提高网站速度并创建更好的用户体验的高级技术。

快速基础知识

在讲解高级技巧之前,我们先快速了解一些基础知识。以下是一些您可以遵循的基本最佳实践清单:

  • 尽可能使用Google Web Fonts 。
  • 如果您使用自定义字体,请尝试将其通过Font squirrel传递,以获得更好的压缩和垂直基线修复。
  • 如果您手动嵌入字体,请使用 WOFF2。WOFF2 的采用率很高(超过 97%),并且压缩率比其他格式高得多。
  • 用于 <link rel="preload" href="/fonts/usual/usual-semi-bold.woff2" as="font" type="font/woff2" crossorigin="anonymous"> 对 HTTP 队列中的字体进行优先级排序。 了解更多
  • 确保字体已使用 缓存cache-control: public, max-age=31536000, immutable。如果您使用 Vercel、Netlify 或 Gatsby Cloud,则可能已经有了良好的缓存策略。
  • 从与您的网站相同的 CDN 下载并提供字体。同样,您可以使用 Vercel、Netlify 和 Gatsby Cloud 来实现这一功能。

现在我们来谈谈高级优化

以下几点可以节省一些 KB,使字体看起来更好,并改善用户体验:

  • 后备字体大小调整
  • 自定义子集
  • 垂直基线修复

后备字体度量调整

使用不属于操作系统的自定义字体需要权衡利弊。浏览器在字体加载之前无法获知其参数;在此之前,浏览器会使用后备字体(例如 Arial、Times New Roman)来计算页面上使用文本的元素的大小。但是,一旦字体加载完毕,就会重新计算大小。

差异可能很大,布局变化将变得明显,尤其是在速度较慢的连接上。

图片描述

此示例比较了两种字体——Times New Roman 和一种名为 Usual 的自定义字体。两种字体的字号均为 16px,行高均为 1.2px,但请注意,对于同一段文本,它们的长度存在差异。

图片描述

最近,一些与后备和自定义字体指标相匹配的新 CSS 属性得到了广泛采用。

上升覆盖

下降覆盖

行间隙覆盖

行间隙覆盖

这听起来很棒,但你真的能做到吗?Google Aurora 团队的Katie Hempenius 和 Kara Erickson@next/font为此创建了一个算法,但它需要自动化解决方案才能发挥最佳性能。Next.js 团队最近在 v13 的更新包中宣布了对此的支持。我们的团队也采用了同样的方法,并将该算法封装在一个 CLI 中,该 CLI 可以生成 CSS 来调整后备字体指标;我们称之为 Fontpie。

github.com/pixel-point/fontpie

这个命令使用起来非常简单。以下是示例命令:

npx fontpie ./roboto-regular.woff2 --name Roboto
Enter fullscreen mode Exit fullscreen mode

输入此命令将返回以下 CSS,无论使用哪种框架或语言,您都可以将其嵌入到项目中:

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('roboto-regular.woff2') format('woff2');
}

@font-face {
  font-family: 'Roboto Fallback';
  font-style: normal;
  font-weight: 400;
  src: local('Times New Roman');
  ascent-override: 84.57%;
  descent-override: 22.25%;
  line-gap-override: 0%;
  size-adjust: 109.71%;
}

html {
  font-family: 'Roboto', 'Roboto Fallback';
}
Enter fullscreen mode Exit fullscreen mode

这个 CSS 解决方案的工作原理如下:(1) 我们声明一个新的字体——Roboto;(2) 然后我们声明另一个名为“Roboto Fallback”的字体,该字体使用本地 Times New Roman 字体,但应用了度量调整。这将完全缓解任何布局偏移。

图片描述

正如您在图像中看到的,经过公制调整的 Times New Roman 现在占用与 Usual 字体相同的空间。

图片描述

此技术与除 Safari 之外的所有现代浏览器兼容。

自定义子集

此技术可以减少字体中嵌入的字符数量。字体的字符数通常远超项目所需,因此使用仅包含所需字符的子集可以显著减小字体大小。

图片描述

Google Web Fonts 有一个很棒的 AP​​I 来创建字体子集。我们以Space Grotesk字体为例 。常规 (400) 字体大小为 15KB,采用 WOFF2 格式。嵌入链接如下所示

<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk&display=swap" rel="stylesheet" />
Enter fullscreen mode Exit fullscreen mode

要定义子集,您只需向 URL 添加额外的 &text 参数;例如:

<link
  href="https://fonts.googleapis.com/css2?family=Space+Grotesk
&display=swap&text=HelloWorld"
  rel="stylesheet"
/>
Enter fullscreen mode Exit fullscreen mode

当你有一个“时尚”的标题,其字体与网站其他部分不同时,这一点尤其有用。在这种情况下,你可以定义一个仅包含该标题字符的子集。在上面的示例中,自定义子集将字体大小缩小到了 1KB。

下面的屏幕截图说明了当字母不存在于子集中时字符的样子。

图片描述

下面列出了一些流行的子集,您可以将其复制/粘贴并插入到 Google Web Font 或 Font Squirrel 中以获取您想要使用的精确集合。

热门子集;复制/粘贴并编辑它们以满足您的需求

小写

abcdefghijklmnopqrstuvwxyz
Enter fullscreen mode Exit fullscreen mode

大写

ABCDEFGHIJKLMNOPQRSTUVWXYZ
Enter fullscreen mode Exit fullscreen mode

数字

0123456789
Enter fullscreen mode Exit fullscreen mode

高音调

ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞߌŸ
Enter fullscreen mode Exit fullscreen mode

低声部

àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿıœƒ
Enter fullscreen mode Exit fullscreen mode

Alt 标点符号

¡«»¿‚„‹›
Enter fullscreen mode Exit fullscreen mode

数学符号

ª¬±µº÷Ωπ‰⁄∂∆∏∑√∞∫≈≠≤≥
Enter fullscreen mode Exit fullscreen mode

印刷术

§©®°¶·†‡•™◊fifl
Enter fullscreen mode Exit fullscreen mode

货币

£¥ƒ€
Enter fullscreen mode Exit fullscreen mode

标点

!"#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~–—‘’“”…
Enter fullscreen mode Exit fullscreen mode

变音符号

¨¯´¸ˆˇ˘˙˚˛˜˝
Enter fullscreen mode Exit fullscreen mode

例如,下面定义的Space Grotesk子集包括大写字母、小写字母、数字、标点符号和货币,最终得到的字体自定义子集只有6KB。

https://fonts.googleapis.com/css2?family=Space+Grotesk&display=swap&text=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!%22#$%&'()*+,-./:;%3C=%3E?@[\]^_%60{|}~%E2%80%93%E2%80%94%E2%80%98%E2%80%99%E2%80%9C%E2%80%9D%E2%80%A6$
Enter fullscreen mode Exit fullscreen mode

自定义字体子集

如果您使用自定义字体(例如 Adob​​e Fonts 中的字体),情况会变得更糟。许多此类字体并未针对网页使用进行优化,并且包含许多不必要的字符。这些字体的大小很容易达到 30KB。Font Squirrel 允许您轻松创建自定义字体子集;只需将字体以 TTF 或 OTF 格式拖放到 Font Squirrel 中,启用专家模式并进行自定义子集设置即可。

图片描述

创建子集非常简单;只需勾选要保留的子集,或在“单字符”字段中填写一个确切的字符即可。例如,版权符号显示在“印刷体”子集类型中,但如果您只需要 ©,请将其添加到“单字符”字段。

垂直基线修复

使用 Font Squirrel 修复字体

使用自定义字体或未优化的字体时,另一个潜在问题是垂直基线可能不正确。例如:

图片描述

使用这些字体可能会导致间距不一致,例如上图所示,即顶部的填充小于底部的填充,而在 CSS 中,填充是相同的。
有时,将字体传递给 Font Squirrel 可能会自动修复此问题。

图片描述

如果这不起作用,您可以使用“自定义调整”来解决这个问题。虽然找到合适的指标组合需要时间,但它可以解决问题。

图片描述

使用 Capsize

Capsize 是一个使用字体元数据的库,它可以根据大写字母的高度调整文本大小,同时修剪大写字母上方和基线下方的空间。它使用 :before 和 :after 伪元素应用 CSS 规则,调整 margin-top 和 margin-bottom 的值,使文本在框内完美调整大小,占据整个空间。

图片描述

示例结果:

// For 48px
.css-dpa7xb::before {
  content: '';
  margin-bottom: -0.1432em;
  display: table;
}

.css-dpa7xb::after {
  content: '';
  margin-top: -0.2142em;
  display: table;
}

// For 24px

.css-1m2jnlz::before {
  content: '';
  margin-bottom: -0.322em;
  display: table;
}

.css-1m2jnlz::after {
  content: '';
  margin-top: -0.393em;
  display: table;
}
Enter fullscreen mode Exit fullscreen mode

这是一个非常易于使用的解决方案,100% 有效。它只需要为页面上使用的每个字体大小添加额外的 CSS 代码。我仍然建议先尝试 Font Squirrel 的自动修复功能,并在必要时尝试 Capsize。

概括

让我们回顾一下本文所学到的内容:

  • 调整后备字体指标是一种简单、快速的修复方法,您可以在Fontpie 或的帮助下在每个项目中使用它 next/font
  • 删除与您的用例无关的字体​​子集,特别是如果在 Hero 部分仅出于设计目的使用自定义时尚字体。
  • 请留意字体的垂直基线,如果您意识到必须保持按钮内的填充与顶部和底部不同才能使文本看起来居中,请尝试修复它。

使用这些技巧可以修复字体的视觉问题,同时节省更多 KB。如果您喜欢这篇文章并想了解更多网页技巧, 请在 Twitter 上关注我

文章来源:https://dev.to/alex_barashkov/advanced-web-font-optimization-techniques-2n1f
PREV
比较 Gatsby 和 Next.js 在网站开发中的应用
NEXT
10 项 Java 开发人员急需的技能