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 小时前
浅谈前端架构设计与工程化
前端·前端架构设计
郝YH是人间理想5 小时前
系统架构设计师案例分析题——web篇
前端·软件工程
Evaporator Core5 小时前
深入探索:Core Web Vitals 进阶优化与新兴指标
前端·windows
初遇你时动了情6 小时前
html js 原生实现web组件、web公共组件、template模版插槽
前端·javascript·html
QQ2740287566 小时前
Soundness Gitpod 部署教程
linux·运维·服务器·前端·chrome·web3
前端小崔6 小时前
从零开始学习three.js(18):一文详解three.js中的着色器Shader
前端·javascript·学习·3d·webgl·数据可视化·着色器
哎呦你好7 小时前
HTML 表格与div深度解析区别及常见误区
前端·html
运维@小兵7 小时前
vue配置子路由,实现点击左侧菜单,内容区域显示不同的内容
前端·javascript·vue.js
koiy.cc7 小时前
记录:echarts实现tooltip的某个数据常显和恢复
前端·echarts
一只专注api接口开发的技术猿7 小时前
企业级电商数据对接:1688 商品详情 API 接口开发与优化实践
大数据·前端·爬虫