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 的范围内,所以浏览器不会尝试获取字体文件。


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

相关推荐
百万蹄蹄向前冲39 分钟前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5811 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
ssshooter2 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry3 小时前
Jetpack Compose 中的状态
前端
dae bal3 小时前
关于RSA和AES加密
前端·vue.js
柳杉3 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog4 小时前
低端设备加载webp ANR
前端·算法
LKAI.4 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy4 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js