# 在网页里使用字体：@font-face 的现代写法

本文介绍现在推荐的网页字体写法。以前为老浏览器准备的 EOT、SVG 字体格式和各种兼容写法，现在已经不需要了。

## 最简单的写法

把字体文件（`.woff2`）放到你的网站上，然后在 CSS 里声明：

```css
@font-face {
  font-family: "LXGW WenKai";
  src: url("/fonts/LXGWWenKai-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

body {
  font-family: "LXGW WenKai", "PingFang SC", "Microsoft YaHei", sans-serif;
}
```

要点：

- **`font-family`**：你给这款字体起的名字，下面的样式用同一个名字引用。
- **`src`**：只写 WOFF2 就够了，所有主流浏览器都支持。`format("woff2")` 告诉浏览器这是什么格式，不支持的浏览器会直接跳过，不会白白下载。
- **`font-weight`、`font-style`**：说明这个文件是什么粗细和样式。同一字体的常规体和粗体各写一个 `@font-face`，`font-family` 名字相同、`font-weight` 不同。
- **后备字体**：`font-family` 后面跟上系统字体和通用字体族（如 `sans-serif`），网页字体还没下载好或加载失败时就用它们显示。

## 可变字体

可变字体一个文件包含一段连续的粗细，`font-weight` 写成一个范围：

```css
@font-face {
  font-family: "Source Han Sans SC VF";
  src: url("/fonts/SourceHanSansSC-VF.otf.woff2") format("woff2");
  font-weight: 250 900;
  font-display: swap;
}
```

之后在样式里用 `font-weight: 350` 这样的任意数值都可以。

## font-display：字体还没下载好时怎么显示

| 值 | 效果 | 适合 |
|---|---|---|
| `swap` | 先用后备字体显示文字，网页字体下载好后马上换上 | 标题、品牌字等一定要用这款字体的地方 |
| `fallback` | 极短时间内不显示文字，之后用后备字体；只在短时间内下载好才换上 | 正文 |
| `optional` | 极短时间内没下载好就一直用后备字体，不再替换 | 对稳定性要求高、字体只是锦上添花的页面 |
| `block` | 最多隐藏文字一小段时间，等字体下载 | 图标字体等必须用原字体才能看懂的情况 |
| `auto` | 交给浏览器决定 | 不推荐，各浏览器表现不一致 |

中文字体文件大，一般用 `swap` 或 `fallback`，避免页面长时间看不到文字。

## unicode-range：只在需要时下载

`unicode-range` 告诉浏览器这个文件包含哪些字符。页面上没有用到这些字符时，浏览器就**不会下载**这个文件：

```css
/* 英文和数字部分 */
@font-face {
  font-family: "LXGW WenKai";
  src: url("/fonts/wenkai-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+2000-206F;
  font-display: swap;
}

/* 常用汉字部分 */
@font-face {
  font-family: "LXGW WenKai";
  src: url("/fonts/wenkai-cjk-01.woff2") format("woff2");
  unicode-range: U+4E00-4FFF;
  font-display: swap;
}
```

几个 `@font-face` 用同一个 `font-family` 名字，浏览器会根据页面上实际出现的字符，只下载需要的那几个文件。这是中文网页字体的基本做法，详见[《中文网页字体为什么要拆分子集》](https://docs.cocobook.com/link/598)。

## 提前加载最重要的字体

首屏一定会用到的字体文件，可以在 `<head>` 里提前加载：

```html
<link rel="preload" href="/fonts/wenkai-latin.woff2"
      as="font" type="font/woff2" crossorigin>
```

注意必须写 `crossorigin`，否则浏览器会重复下载。只给一两个最关键的文件加，不要给所有分片都加。

## 字体放在别的域名上

字体文件放在另一个域名（比如单独的静态资源域名）上时，那边的服务器需要返回允许跨域的响应头 `Access-Control-Allow-Origin`，否则浏览器会拒绝使用这个字体。

## 使用前先看许可

把字体放到网站上供浏览器下载，属于“网页嵌入”。开源字体一般允许，商业字体通常需要单独的网页字体许可。见[《用字前先看许可：能不能商用、能不能改、能不能嵌入》](https://docs.cocobook.com/link/599)。

## 参考资料

- MDN：[@font-face](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face)
- MDN：[font-display](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face/font-display)
- MDN：[unicode-range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range)