摘要:Web 字体的加载对于 Web 性能来说通常很糟糕,而且没有一种字体加载策略可以特别有效地解决这个问题。 在即将推出的字体选项这个属性可能最终会解决让备选字体与最终字体的显示一致的问题。
长期以来字体加载一直是比较影响Web性能的问题,但是目前也没有更好的选择。如果您想使用网络字体,你的选择基本上是隐藏字体闪烁(又名 FOIT),在字体下载之前隐藏文本或无样式文本的闪烁(FOUT),您最初使用备选系统字体,然后将其升级到下载的网络字体。 老实说,这两种选择没有真正的谁好谁坏,因为两者的表现都不是太令人真正的满意。

font-display 不是应该解决这个问题吗?

@font-face 的 font-display 属性为 Web 开发人员提供了选择如何渲染,然而以前是由浏览器决定是哪种渲染方式(过去 IE 和 Edge 支持 FOUT,而其他浏览器支持 FOIT)。 除此之外,它并没有真正解决问题。

许多网站在首次出现时倾向于设置font-display:swap,Google Fonts 甚至在 2019 年将其设为默认值。 可能它的想法是尽可能快地显示文本,这样对性能看起来似乎更好,即使它采用备选字体,然后在最终下载时交换字体。

当时我也支持这一点,但是当网络字体下载和字符由于字体之间的差异而扩展(或收缩)时,我越来越发现自己对“hydration effect”感到沮丧。 与大多数出版商一样,Smashing Magazine 也使用网络字体,下面的屏幕截图显示了初始渲染(使用备选系统字体)和最终渲染(使用网络字体)之间的区别:
image.png
现在当这两种方式并排放置时,网络字体的渲染展示要好得多,并且它确实符合 Smashing Magazine 品牌。 但是我们也看到两种字体的文本布局存在很大差异, 字体大小非常不同。因此,屏幕内容会四处移动。 在这个 Core Web Vitals 和 Cumulative Layout Shifts(目前来看是相当正确的一种方式) 验证下,使用font-display: swap则认为对用户是一种不好的体验了。

因为我确实发现文本渲染后闪现是个非常烦人的体验,所以目前我已经在我开发的网站上默认设置font-display: block。 虽然block属性确实不会阻止字体闪现(字体仍然以不可见的文本形式渲染),但它至少使用户的感受不那么明显。 我还通过预加载字体进行了优化,我通过自托管子集字体使这些字体尽可能小——因此访问者通常只在很短的时间内看到备选字体。 对我来说,由于swap 的“block period”太短了,所以我更愿意多等一会儿,让初始化渲染正确。

使用font-display: optional可以解决FOIT和FOUT—-有代价

另一种选择是使用 font-display: optional 。 这个属性基本上可以使 Web 字体成为可选的,或者换句话说,如果在页面需要时字体不存在,则由浏览器决定永远不要交换它。 有了这个选项,我们基本上只使用已经下载的字体来避免 FOIT 和 FOUT。

如果页面加载后网络字体不可用,我们会回退到备选字体,但导航到下一页(或重新加载此页面)将使用该字体——因为它应该已经完成下载。 但是,如果 Web 字体对站点来说不重要,那么完全删除它可能是个好主意——这对 Web 性能来说甚至更好!

网站的第一印象很重要,因为市场上的网站不加载网络字体似乎有点太多了。我认为在人们的潜意思印象中,网站的某些设置默认是“关闭”的,如果打开了,则会影响人们的某些使用方式(顺便说一下,这没有证据可以证明这一点)。

因此,所有字体的选择都有其缺点,包括根本不使用网络字体或使用系统字体(这是有限制的——但可能不像许多人想象的那样有限制!)(译者根据经验来看,很多用户的电脑装的字体不是很全,有些字体版本还不一致,比如微软雅黑,windows8之后就进行过一次字体升级,有兴趣的可以去对比一下)。

使您的备用字体与您的网络字体更加匹配

Web 字体加载的秘籍是让备选字体更接近实际的 Web 字体,以尽可能减少明显的偏移,从而减少使用swap的影响。 虽然我们永远无法完全避免这些转变,但我们可以做得比上面的屏幕截图更好。 Monica Dinculescu 的 Font Style Matcher 应用程序经常在字体加载文章中被引用,并在这里给出了应该可以实现的精彩一幕。 它允许您用两种不同的字体覆盖相同的文本以查看它们的不同,并调整字体设置以使它们更紧密地对齐:
image.png

不幸的是,字体样式匹配的问题是我们不能让这些 CSS 样式只应用于回退字体,所以我们需要当 web 字体加载时,使用 JavaScript 和 FontFace.load API 来应用(或恢复)这些样式差异。

代码量虽然并不大,但仍然感觉比应该的结果(成就)多一点。 尽管正如 Zach Leatherman 在 2019 年的精彩演讲中所解释的那样,使用 JavaScript API 还具有其他优势和可能性——但您可以减少回流并处理data-server模式和prefers-reduced-motion的情况(但请注意 自从那次谈话以来,他们都已经接触过 CSS)。

处理我们已有的缓存字体已经比较棘手,更不用说各种回退样式的差异了。 在 Smashing Magazine 上,我们尝试了许多备选字体的方法,以充分利用不同用户和操作系统安装的系统字体:

  1. font-family: Mija,-apple-system,Arial,BlinkMacSystemFont,roboto slab,droid serif,segoe ui,Ubuntu,Cantarell,Georgia,serif;

知道使用哪种字体,或对每种字体进行单独调整并确保正确应用它们很快就会变得非常复杂。

更好的解决方案即将到来

所以,以上是对目前情况的简要说明。 然而,硝烟弥漫啊。
image.png
正如我之前提到的,应用回退样式差异的主要问题是添加和删除它们。 如果我们可以告诉浏览器这些差异仅针对备选字体会怎样?

这正是CSS Fonts Module Level 5提出的一组新字体描述符所做的一部分。 这些应用于定义单个字体的@font-face 声明。

Simon Hearne 写了关于字体描述符规范的这个提议更新,其中包括四个新的描述符:ascent-override、descent-override, line-gap-override 和 advance-override(自删除以来)。 您可以使用 Simon 创建的 F-mods playground来加载您的自定义和备选字体,然后使用覆盖来获得完美匹配。

但事情似乎又一次发生了变化。 最近,为了支持即将推出的size-ajust描述符,放弃了advance-override,该描述符允许我们通过字形的比例因子(百分比)匹配备选字体和主要 Web 字体来减少布局偏移。

它是如何工作的? 假设您有以下 CSS:

  1. @font-face {
  2. font-family: 'Lato';
  3. src: url('/static/fonts/Lato.woff2') format('woff2');
  4. font-weight: 400;
  5. }
  6. h1 {
  7. font-family: Lato, Arial, sans-serif;
  8. }

然后你要做的是为 Arial 备选字体创建一个 @font-face 并将调整器描述符应用于它。 然后你会得到以下 CSS 片段:

  1. @font-face {
  2. font-family: 'Lato';
  3. src: url('/static/fonts/Lato.woff2') format('woff2');
  4. font-weight: 400;
  5. }
  6. @font-face {
  7. font-family: "Lato-fallback";
  8. size-adjust: 97.38%;
  9. ascent-override: 99%;
  10. src: local("Arial");
  11. }
  12. h1 {
  13. font-family: Lato, Lato-fallback, sans-serif;
  14. }

这意味着最初使用 Lato-fallback 时(因为 Arial 是一种本地字体,无需任何额外下载即可直接使用),通过设置size-ajust和advance-override来使其更接近 Lato 字体。 这是一个额外的@font-face 声明,但肯定比我们之前必须跳过的坑要容易得多!

总体而言,该规范中 @font-face 包含四个主要的描述符:size-adjust、ascent-override、descent-override 和 line-gap-override,还有一些仍在考虑用于下标、上标和其他用例 .

Malte Ubl 创建了一个非常有用的工具,可以在给定两种字体和支持这些新设置的浏览器的情况下自动计算这些设置(稍后会详细介绍!)。 正如 Malte 指出的那样,计算机擅长这种事情! 理想情况下,我们还可以将常用的这些字体的设置公开给 Web 开发人员,比如 可以像谷歌字体这样的字体集合中给出这些提示? 这肯定有助于提高采用率。

现在不同的操作系统可能有些许不同的字体设置,让这些系统都展现的完全正确基本上是一项不可能完成的任务,但这不是目标。 我们的目的是缩小差距,因此使用 font-display: swap 不再是一种不爽的体验,但我们不需要追求optional或没有网络字体的极端。

我们什么时候可以开始使用它?

自 87 版以来,Chrome 中已经提供了其中三个设置,尽管size-ajust描述符在任何稳定的浏览器中尚不可用。 然而,Chrome Canary (chrome92+)已经支持它,Firefox 也支持它,所以这不是一些抽象的、遥远的概念,而是很快就会落地的东西。

目前,该规范有各种各样的免责声明和警告,表明它还没有准备好立即使用,但确实感觉到它已经到了。 与往常一样,我们的设计师和开发人员,在测试它并提供反馈以及不鼓励使用它之间保持平衡,因此实际应用的情况不会因为太多人最终使用早期草案而陷入困境。

Chrome 已经表示他们打算在 7 月 20 日发布的 Chrome 92 中提供size-ajust属性,这可能表明它几乎就可以用了。

所以,目前貌似还没有完全可以使用,但看起来它会在不久的将来到来。 与此同时,试试 Chrome Canary 中的演示,看看它是否可以更接近于解决您的字体加载问题及其造成的 CLS 影响。

翻译有误的地方,请及时反馈联系修改

原文地址: https://www.smashingmagazine.com/2021/05/reduce-font-loading-impact-css-descriptors/
参考内容:
https://deploy-preview-15—upbeat-shirley-608546.netlify.app/perfect-ish-font-fallback/?font=Handlee
https://deploy-preview-15—upbeat-shirley-608546.netlify.app/posts/high-performance-web-font-loading/
https://www.zachleat.com/web/fout-vs-foit/
https://www.zachleat.com/foitfout/