CSS 自定义字体实践

为了更好的视觉体验,设计稿中偶尔会对部分文字、数字会使用了非默认字体,例如 DIN CondensedDIN Alternate 等字体。

DIN Alternate 字体图例 - 侵删请联系

创建字体子集

一般而言,字体文件尺寸不会很小,诚然目前浏览器、网络等外部因素比过去友好得多,尝试在一定程度优化字体文件的大小仍然有意义。

仍旧以 DIN Alternate 字体为例,DIN Alternate Bold.ttf 文件约有 152KB,这 152KB 中包含英文字母、数字、符号和其他的一些字符。而对我们而言,可能只会使用 0-9 这几个数字字符,其他字符纯属浪费网络资源,那么是否有办法只加载 0-9 这几个字符呢?

答案自然是肯定的,可以使用 glyphhanger - npmjs.com 这个包的能力来 "裁剪"原字体文件,取原字体文件中的几个字符生成新的字体子集文件

glyphhanger 的安装大致如下,具体请参考 glyphhanger 文档:

具体请参考 glyphhanger 文档,毕竟写在这里的代码会过时。

bash 复制代码
npm install -g glyphhanger # 全局安装

# 安装部分 python 包
# 目前 Mac 上估计都是 pip3 了
pip3 install fonttools
# 安装用于支持 woff2 字体格式
pip3 install brotli

glyphhanger 的使用也很简单,设置好需要的字体格式、所需要的字符以及字体文件即可。

bash 复制代码
glyphhanger
--formats=woff2,woff,ttf # 要生成的格式
--whitelist=U+30-39,U+2E # 没有办法直接写数字0-9,需要使用U+的表示方式,多个区间使用逗号分隔,U+30-39表示0-9,U+2E表示英文句号
--subset=./DIN\ Alternate\ Bold.ttf # 需要处理的字体

通过 ls -al 看所生成的字体子集文件:

plaintext 复制代码
a@b c % ls -al
total 216
drwxr-xr-x    6 a  d     192  1 28 09:41 .
drwx------@   1 a  d   10496  1 28 09:41 ..
-rw-r--r--    1 a  d    6556  1 28 09:41 DIN Alternate Bold-subset.ttf
-rw-r--r--    1 a  d    4688  1 28 09:41 DIN Alternate Bold-subset.woff
-rw-r--r--    1 a  d    3904  1 28 09:41 DIN Alternate Bold-subset.woff2
-rw-r--r--    1 a  d  152012  1 28 09:41 DIN Alternate Bold.ttf

可以看到其中的 655646883904,即字体子集文件大小只有几KB。

使用字体子集

在 CSS 中使用字体子集时,也有需要注意的地方:

css 复制代码
@font-face {
  font-family: "DIN Alternate";
  src:
    // Mac 和 iOS 中有本地字体
    local("DIN Alternate Bold"),
    url('./assets/fonts/DIN_Alternate_Bold_subset.woff2') format('woff2'),
    url('./assets/fonts/DIN_Alternate_Bold_subset.woff') format('woff'),
    url('./assets/fonts/DIN_Alternate_Bold_subset.ttf') format('truetype');
    // 范围 U+30-39 => 0-9 U+2E => .
    unicode-range: U+30-39,U+2E;
    // 对于 DIN Alternate 来说,只有 Bold 这么一个字体,设不设置 font-weight 看起来没有影响
    font-weight: 700;
}
  1. 对于一些系统中默认存在的字体,可以通过 local() 函数的方式进行使用。
  2. 由于 src 的处理顺序从上到下,所以一般 local() 放在第一项,woff2woffttf 按照顺序列出。

当浏览器解析到可用的字体时,便不会再继续向下寻找,所以这种顺序应该是对网络加载最友好的。

比如对于 Android 设备来说,可能没有 DIN Alternate 字体,则 local() 会失败,接下来该设备支持 woff2 的情况下,那么就只会尝试下载 woff2 文件。

unicode-range 也在一定程度上优化了网络加载,因为只有使用该字体的 element 内容符合 unicode-range 的情况下,浏览器才会从 src 中加载字体文件。

比如 <div style="font-family: 'DIN Alternate'">abc</div> 即便指明使用该字体,但由于其中的内容 abc 不在 unicode-range 的范围内,所以浏览器不会尝试获取字体文件。


到此为止,算是简单地完成了加载自定义字体所需要的全部工作,目前所做的这些可能只算最佳实践的一部分,但应对前端工作中偶尔出现的自定义字体也算够用。

相关推荐
程序员码歌2 小时前
短思考第261天,浪费时间的十个低效行为,看看你中了几个?
前端·ai编程
Swift社区3 小时前
React Navigation 生命周期完整心智模型
前端·react.js·前端框架
若梦plus3 小时前
从微信公众号&小程序的SDK剖析JSBridge
前端
用泥种荷花4 小时前
Python环境安装
前端
Light604 小时前
性能提升 60%:前端性能优化终极指南
前端·性能优化·图片压缩·渲染优化·按需拆包·边缘缓存·ai 自动化
Jimmy4 小时前
年终总结 - 2025 故事集
前端·后端·程序员
烛阴4 小时前
C# 正则表达式(2):Regex 基础语法与常用 API 全解析
前端·正则表达式·c#
roman_日积跬步-终至千里4 小时前
【人工智能导论】02-搜索-高级搜索策略探索篇:从约束满足到博弈搜索
java·前端·人工智能
GIS之路4 小时前
GIS 数据转换:使用 GDAL 将 TXT 转换为 Shp 数据
前端
多看书少吃饭4 小时前
从Vue到Nuxt.js
前端·javascript·vue.js