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


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

相关推荐
森叶4 分钟前
Electron 安装包 asar 解压定位问题实战
前端·javascript·electron
drebander7 分钟前
ubuntu 安装 chrome 及 版本匹配的 chromedriver
前端·chrome
软件技术NINI17 分钟前
html知识点框架
前端·html
深情废杨杨20 分钟前
前端vue-插值表达式和v-html的区别
前端·javascript·vue.js
GHUIJS21 分钟前
【vue3】vue3.3新特性真香
前端·javascript·vue.js
众生回避27 分钟前
鸿蒙ms参考
前端·javascript·vue.js
洛千陨27 分钟前
Vue + element-ui实现动态表单项以及动态校验规则
前端·vue.js
GHUIJS1 小时前
【vue3】vue3.5
前端·javascript·vue.js
&白帝&2 小时前
uniapp中使用picker-view选择时间
前端·uni-app
魔术师卡颂2 小时前
如何让“学源码”变得轻松、有意义
前端·面试·源码