unicode-range是css中用于指定@font-face规则适用unicode字符范围的属性,它本身不触发按需下载,仅控制字符匹配与回退;真正实现按需加载需手动拆分字体文件并为每个子集声明独立@font-face规则。

unicode-range 是什么,它真能按需加载字体子集?
不能。这是最常见的误解——@font-face 中的 unicode-range **只控制字符匹配与回退行为,不触发独立字体文件下载**。浏览器仍会加载整个 src 指定的字体文件(除非你手动拆分并为不同子集声明多个 @font-face 规则)。它的作用是:告诉浏览器“这个字体规则只负责渲染哪些 Unicode 码点”,从而让多个规则共存时能精准分流。
真正实现按需加载的唯一方式:拆成多个独立 @font-face 声明
必须把中文字体、英文字体、图标字体等分别打包为不同文件(如 font-zh.woff2、font-en.woff2、font-icon.woff2),再为每个文件写一条带 unicode-range 的 @font-face 规则。浏览器会按需下载其中被实际用到的那些。
- 确保每个字体文件只包含对应范围的字形(用 fonttools 或 glyphhanger 提取子集)
- 每个
@font-face的font-family名必须一致(否则无法叠加),例如都叫"MyFont" -
unicode-range值要互斥且覆盖完整,避免漏字导致回退到系统字体 - 推荐用十六进制写法,比如中文常用:
U+4E00-9FFF, U+3400-4DBF, U+20000-2A6DF
示例:
@font-face {
font-family: "MyFont";
src: url("font-en.woff2") format("woff2");
unicode-range: U+0020-007E, U+00A0-00FF;
}
<p>@font-face {
font-family: "MyFont";
src: url("font-zh.woff2") format("woff2");
unicode-range: U+4E00-9FFF;
}</p><p>@font-face {
font-family: "MyFont";
src: url("font-icon.woff2") format("woff2");
unicode-range: U+F100-F1FF;
}</p>
常见踩坑:unicode-range 写错导致字体不生效
浏览器对 unicode-range 解析严格,写错一点就整条规则失效(表现为该范围字符回退到默认字体,且对应字体文件也不会被加载)。
- 不能用十进制或字符字面量(如
U+e9不行,必须U+00E9;U+"a"完全非法) - 范围之间必须用逗号分隔,末尾不能有逗号
- 连字符
-前后不能有空格(U+4E00 - 9FFF无效) - 单个码点要补零到至少 4 位(
U+20错,U+0020对) - 超出 BMP 的增补字符(如 emoji)必须用代理对或 UTF-32 表示,例如
U+1F600-1F64F是合法的
验证是否真的按需加载:看 Network 面板和 computed font-family
光看样式面板没用。打开 DevTools 的 Network 标签页,刷新页面,观察哪些字体文件被请求;再选中一个中文元素,看 Computed 面板里的 font-family 值,以及最终生效的 font-family 后面是否标注了具体字体文件名(Chrome 会显示 “from font-face”)。如果某个子集字体没被请求,但对应字符却显示正常,说明它被别的规则或系统字体兜底了——这时候 unicode-range 可能没覆盖到,或者优先级被其他规则覆盖。
复杂点在于:CSS 字体匹配是逐字符进行的,而浏览器不会为每个字符发起单独请求;它只在首次遇到某 @font-face 覆盖的字符时,才加载对应 src。所以测试时得确保页面里确实存在落在目标 unicode-range 内的字符,且没有被更高优先级的字体规则拦截。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











