shadowfish和他的代码

vuePress-theme-reco shadowfish    2020 - 2023
shadowfish和他的代码

Choose mode

  • dark
  • auto
  • light
时间轴

shadowfish

49

Article

42

Tag

时间轴

5步优化web字体

vuePress-theme-reco shadowfish    2020 - 2023

5步优化web字体

shadowfish 2021-05-21 前端

本文原文出处:https://iainbean.com/posts/2021/5-steps-to-faster-web-fonts/ ,我进行了翻译和归纳整理。

在这篇文章中,我将介绍5种提示web字体性能的方法。

# 1.使用最现代的字体格式

WOFF2 是目前最小、最高效的web字体格式。在CSS文件中使用@font-face的时候,得确保WOFF2字体在TTF这样的老格式前面。浏览器会默认使用最先声明的字体。

@font-face {
  font-family: 'Typefesse';
  src: url('typefesse.woff2') format('woff2'),
    url('typefesse.woff') format('woff');
}

除非需要支持IE8,WOFF2和WOFF完全可以满足一切需求。如果连IE11都不用支持,WOFF2就够了。

如果手上只有TTF文件,可以用Online Font Converter 来进行转换。

# 2.使用font-display属性

以下是两种字体载入策略:

  1. FOIT(Flash of *Invisible* Text)是浏览器下载完毕相应字体前,文本不可见
  2. FOUT(Flash of *Unstyled* Text)是浏览器下载完毕相应字体前,文本使用后备字体渲染

这两种策略都不是完美的。如果使用自定义字体,其中的一种可能会在用户初次访问时出现(之后的载入浏览器基本都会从缓存中加载字体)。如果在之前的@font-face代码中插入font-display属性,可以指定我们想要的策略。

@font-face {
  font-family: 'Typefesse';
  src: url('typefesse.woff2') format('woff2'),
    url('typefesse.woff') format('woff');
  font-display: swap;
}

font-display属性有五种可行值:

# auto

auto是浏览器默认的值(大多数浏览器倾向于FOIT)。

# swap

image.png

swap告诉浏览器我们想在自定义字体加载完毕前使用后备(fallback)字体渲染文本(也就是FOUT)。不管花了多少时间加载自定义字体,只要加载完毕,文本马上就会切换到该字体。这允许用户直接开始阅读文本,但要确保后备(fallback)字体不要和自定义字体差别太大,不然在切换时会导致较大的布局变化。

# block

image.png

如果我们更倾向于让浏览器在字体载入完毕前隐藏文本(即FOIT),我们可以使用font-display:block。文本不会永远隐藏,如果自定义字体没有在特定时间内(通常是3秒),浏览器会自动使用后备(fallback)字体,但在自定义字体载入后,会自动切换。

如果你感觉FOUT策略视觉效果不好,这是最佳的选择。但是得记得,一开始文本不可见的时候,你的页面对于用户来说不可读的。

# fallback

image.png

fallback和swap很像,有以下两个区别:

  1. 开始时有一个很短的(约等于100ms)的空白时间,此时文本被隐藏,然后显示后备(fallback)字体。
  2. 如果自定义字体没有在短时间内载入(约3s),后备字体会一直使用下去,不会再切换。

如果不在乎用户是不是能在第一次载入网站时看到自定义字体,fallback是一个好的选择。

# optional

image.png

optional和fallback很像。它给字体一个很短的时间(约100ms)加载,如果超时则不再会切换字体。然而,它还有一个额外的特性——允许浏览器决定在字体加载速度过慢时,放弃字体的加载。

每个页面上的字体都会有自己的FOIT/FOUT策略,他们在自己加载完毕后执行切换,而不是所有字体都加载完毕才切换。这回导致一些特殊行为(参见the Mitt Romney Web Font Problem )。为了对字体加载策略的完全掌控,需要使用JS来解决。

# 3.预载入字体文件

为了减小FOIT/FOUT的时间,自定义字体的载入得尽可能更快一点。在<head>标签中使用link rel="preload"可以告诉浏览器提前载入字体。在<head>标签前(在所有CSS前)添加如下代码,并给你的字体设置href属性:

<link rel="preload" href="/typefesse.woff2" as="font" type="font/woff2" crossorigin>

通过添加这个标签,浏览器加载时会立刻载入字体文件,而不是在它找到CSS中对该字体的引用和使用它的DOM元素时才开始载入。

浏览器通常只会下载当前页面需要的字体。可以使用preload(预载入)来覆盖这一行为,强制浏览器下载未被使用的字体。这会带来更高的加载成本,因此,每个字体都应该只被preload(预载入)一种字体格式(如果有WOFF2的话,就用WOFF2)。

越多字体被preload(预载入),这篇文章描述的优化方法收益越低。因此,优先加载用户不需要滚动页面就可以看到的字体(100vh)。

可以在这里看到更多关于预载入的文章:Preload: What Is It Good For?

# 4.创建字体文件的子集

通过创建字体子集,可以生成一个更小的字体文件,只包含我们需要的字形(独立的字符和符号)。可以使用Everything Fonts上的Font Subsetter 来生成字体子集。这可以大大降低字体文件的大小。

字体子集化是一个非常有效方法,但是这可能也会带来一些缺点。如果你正在开发一个呈现用户自己创建的内容的网站,就需要注意用户可能会输入任何子集化可能已经被排除的字符。

# 5.把字体托管在自己的主机上

这一步和上面四步不同,这不是通用的方法。直接使用Google Fonts 或Adobe Fonts 而不是自己主机上托管字体的原因有两个:

  1. 他们是获得特定的字体最便宜或者唯一合法的途径。
  2. 他们很方便——比起下载字体文件,转换、生成子集,编写font-face,字体托管服务直接复制粘贴HTML代码就可以引入字体。

如果你纯粹是为了方便使用Google Fonts,可以试试google-webfonts-helper 。这个工具能帮你一键下载所需的字体文件和CSS代码。

你可能听说过,如果一个用户之前访问过网站,浏览器不会再下载从之前一样的源获取的一样的字体,因为它们被缓存了。

这可能是真的,但是我没发现这个机制肉眼可见地生效来改进载入速度。事实上,为了避免跟踪,Chrome和Safari都明确阻止来自其他域的第三方资源进行缓存

这是把字体托管在自己的主机上的好处:

# 性能

解析域名需要时间。你可以使用[预连接]( resource hints )技术减轻这个问题,但开启一个新的TCP连接肯定会有性能问题。这可能就是Google一些自己的网站现在都使用自己托管的字体的原因。

# 隐私

有偿的字体服务商(如Adobe Fonts)为了计费的需求,需要检测页面内容,但是他们可能会收集更多不必要的信息。如果可以,在CSS中加载字体(<link rel="stylesheet">)而不是在javaScript中(<script>),这样减少第三方获取你用户的信息数据量。

# 控制

自己托管字体当然可以获得完全的控制权限。你可以指定字体载入方式,创建子集,声明font-display设置,指定浏览器缓存字体文件的时间。

# 可靠

第三方服务可能会面临减速、下线等问题。自己托管字体的好处是只要网站能运行,字体肯定也可以。

# 总结

每个方法都有自己的优点,结合起来可以带来巨大的提示。如果你决定实现一些文章中提到的方法,可以用Lighthouse 或Web Page Test 在你修改前后进行测试,看看每个方法带来的效果。