本文介绍了如何在网页中使用font-face规则加载开源字体RobotoMono,包括下载字体、定义font-face规则,以及利用font-display属性控制字体加载以改善用户体验,避免FOUT和FOIT问题。
介绍
@font-face
是一个 CSS at-rule,用于定义自定义字体。通过 @font-face
,您可以提供一个路径到与您的 CSS 文件托管在同一服务器上的字体文件。这个规则已经存在了相当长的时间,但是有一个更新的属性 font-display
,它带来了新的加载选项。
在本教程中,我们将下载流行的开源字体 Roboto Mono,并使用 @font-face
在一个示例网页上加载该字体。为了创建最佳的用户体验,我们将使用 font-display
属性来自定义加载字体的方式和时间。
先决条件
- 一个您喜欢的代码编辑器,比如
nano
或 Visual Studio Code - 一个网络浏览器
- 对 HTML 基础知识的了解。您可以查看我们的教程系列《如何使用 HTML 构建网站》来进行介绍。
步骤 1 — 下载字体并构建网页
在我们开始探索 @font-face
规则之前,让我们先设置一个示例网页和目录。
从一个工作目录开始,为我们的网站创建一个新文件夹和一个用于存放字体文件的子目录:
mkdir -p ./website/fonts/
进入我们新项目的根目录 website
:
cd website
我们将从这里运行所有剩余的命令。
现在我们将使用 curl
命令来下载 Roboto Mono 字体。我们将使用一个名为 google-webfonts-helper
的流行应用程序,它允许我们在单个、整洁的 GET
请求中直接从 Google 的内容交付网络中下载多个字体。
让我们下载 Roboto Mono 的两种不同样式和粗细,即 regular
和 700italic
:
curl -o ./fonts/fontfiles.zip "https://google-webfonts-helper.herokuapp.com/api/fonts/roboto-mono?download=zip&subsets=latin,latin-ext&variants=regular,700italic&formats=woff,woff2,ttf"
请注意我们正在指定我们从 Roboto Mono 字体系列中想要的 variants
。然后我们为每个指定我们想要的 formats
。我们请求 ttf
、woff
和 woff2
格式。woff2
格式是最现代的网络字体格式,但是一些浏览器仍然缺乏对 woff2
的支持。因此,我们还提供了一个回退选项,即 woff
格式,它支持到 Internet Explorer 9,并且一个 TrueType 格式,或者 ttf
。这将给我们出色的覆盖范围,但是当我们编写我们的 CSS 时,我们将使用标准字体提供更多的回退选项。font-display
属性也将帮助我们管理如何为不同的用户加载字体。
现在将下载的内容解压到我们的 ./fonts
文件夹中。在运行 Linux 和 macOS 的机器上,使用以下命令:
unzip ./fonts/fontfiles.zip -d ./fonts
检查 ./fonts
文件夹的内容:
ls ./fonts
现在我们找到了六个新文件—每个字体有一个 .ttf
、一个 .woff
和一个 .woff2
文件。
字体下载完成后,让我们编写一些 CSS 并将其用于样式化 HTML 元素。
步骤 2 — 使用 @font-face
规则
在这一步中,我们将使用 @font-face
属性应用我们下载的字体。
使用 nano
或您喜欢的文本编辑器,创建并打开一个名为 style.css
的文件:
nano style.css
添加以下内容,这将定义带有我们文件路径的 @font-face
规则:
@font-face { font-family: 'Roboto Mono', monospace; src: url(fonts/roboto-mono-v12-latin-regular.woff2) format('woff2'), url(fonts/roboto-mono-v12-latin-regular.woff) format('woff'), url(fonts/roboto-mono-v12-latin-regular.ttf) format('truetype'); } @font-face { font-family: 'Roboto Mono', monospace; src: url(fonts/roboto-mono-v12-latin-700italic.woff2) format('woff2'), url(fonts/roboto-mono-v12-latin-700italic.woff) format('woff'), url(fonts/roboto-mono-v12-latin-700italic.ttf) format('truetype'); font-weight: 700; font-style: italic; } h1, p { font-family: 'Roboto Mono', monospace; } h1 { font-family: 'Roboto Mono', monospace; font-weight: 700; font-style: italic; }
让我们逐块地检查这段代码。
始终首先在主 CSS 文件中定义您的 @font-face
at-rules。@font-face
规则的最基本版本需要 font-family
和 src
属性。在我们的第一个块中,我们为 font-family
提供了 Roboto Mono
作为值,并为 src
提供了我们三个文件的路径,每个文件都有不同的格式,并按优先级降序排列。
在我们的第二个块中,我们提供了相同的 font-family
值,但是我们使用了我们的 Roboto Mono 的 700italic
版本的路径。然后我们定义了两个属性,font-weight
和 font-style
。我们将使用这些属性来定义我们想要使用第二个版本的 Roboto Mono。
在我们接下来的两个块中,我们为
和
元素定义了自定义样式。请注意我们如何使用 font-family
来同时定义两者,然后在特定于
的块中添加了 font-weight
和 font-style
。这将使我们的 H1
标题以 Roboto Mono 700italic
而不是 Roboto Mono regular
渲染。
保存并关闭文件。
现在让我们创建一个带有一些
和
标签的小型 HTML 页面。
创建并打开一个名为 index.html
的新文件:
nano index.html
添加以下代码,这将定义一个标题和一行文本:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>CSS @font-face</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1> Roboto Mono 字体,700italic </h1> <p> Roboto Mono 字体,regular </p> </body> </html>
保存并关闭文件。
在网络浏览器中加载 index.html
。您将看到您的标题以 Roboto Mono 700italic
渲染,而您的段落文本以 Roboto Mono regular
渲染,就像这样:
Roboto Mono 字体,700 italic
Roboto Mono 字体,regular
通过我们的 @font-face
属性的工作,现在让我们使用 font-display
来配置字体的加载方式和时间。
第三步 — 使用 font-display
控制字体加载
通过使用 font-display
,我们可以精确控制字体的加载方式。这可以极大地改善在使用自定义字体时的用户体验。
有时,在使用自定义字体时,用户在页面首次加载时可能会遇到 FOUT(无样式文本闪烁)或 FOIT(不可见文本闪烁)。一些浏览器选择立即显示文本,即使自定义字体尚未加载。浏览器在自定义字体完全加载后会切换到该字体,但这会导致 FOUT。其他浏览器会在短暂时间内隐藏文本,直到自定义字体加载完成,这会导致 FOIT。如果在这段时间内字体未加载,浏览器将使用备用字体。
解决 FOUT 的一种方法是使用类似 Font Style Matcher 的工具,找到一个尽可能接近自定义字体的备用字体,以减轻字体更改的突然感。然而,我们可以使用 font-display
属性更优雅地处理这些问题。
为了解决加载问题,font-display
可以取以下 5 个值:
auto
: 使用浏览器的默认行为,具体行为会有所不同。block
: 文本首先会在短暂时间内隐藏,但在自定义字体可用时会切换到该字体。这个值被认为有一个无限的swap
期。swap
: 文本从不会被隐藏,并在自定义字体可用时切换到该字体。这也提供了一个无限的切换期。fallback
: 文本在一个非常短的时间内被隐藏(块期),然后有一个短暂的切换期。如果自定义字体在切换期内未加载,则不会加载。optional
: 文本被给予一个非常短暂的块期来加载(~100ms)。如果字体在该块期内未加载,则使用备用字体,自定义字体则不会加载。然而,字体仍会在后台下载并缓存。这意味着在后续页面加载时,自定义字体将在缓存中可用,然后会立即加载。
font-display
的 optional
值为许多字体加载情况提供了一个强大的解决方案。让我们将其添加到我们自己的 CSS 中。
重新打开 style.css
:
nano style.css
现在添加下面的代码:
@font-face { font-family: 'Roboto Mono', monospace; src: url(fonts/roboto-mono-v12-latin-regular.woff2) format('woff2'), url(fonts/roboto-mono-v12-latin-regular.woff) format('woff'), url(fonts/roboto-mono-v12-latin-regular.ttf) format('truetype'); font-display: optional; } @font-face { font-family: 'Roboto Mono', monospace; src: url(fonts/roboto-mono-v12-latin-700italic.woff2) format('woff2'), url(fonts/roboto-mono-v12-latin-700italic.woff) format('woff'), url(fonts/roboto-mono-v12-latin-700italic.ttf) format('truetype'); font-weight: 700; font-style: italic; font-display: optional; } h1, p { font-family: 'Roboto Mono', monospace; } h1 { font-family: 'Roboto Mono', monospace; font-weight: 700; font-style: italic; }
现在我们的自定义字体要么加载得如此迅速以至于用户永远不会经历 FOUT 或 FOIT,要么根本不加载。然而,它仍会在刷新或访问更多页面时立即下载和加载。
结论
在本教程中,我们下载了一个自定义字体,并使用 @font-face
属性将其添加到网页中。然后,我们使用 font-display
属性来管理自定义字体的加载方式,如果有的话。要了解更多关于 font-display
和相关属性的信息,请考虑查阅 Mozilla 开发者网络上的相关文档。