CSS – Font Family
前言
font-family 虽然只是一个 CSS 属性, 但是牵连许多东西, 所以独立一篇来讲.
网站一般上会使用 Google Fonts 作为 font-family, 下面会以一个 Google Fonts 为例子. 逐步解析它背后的 CSS 知识.
Pick a Google Font
到官网 fonts.google.com, 随便选一个 font 作为 font-family.

我选了 material 的 Roboto.
Select font-style and font-weight
知识点
1. 不是每个字体都有支持 Italic
2. 不是每个字体都支持 100 – 900 的 weight
3. 网站有使用到的才选择. 每一个 style 和 weight 都是一份字体文件, 下载越多越慢.
4. 常用的 weight 300, 400, 500, 700, Italic 尽量就别用了

作为示范, 我选了 normal 300, 400, 500, 700 和 Italic 400
右边点击 select, 就可以看见 selected 的 style 和 weight 了

Import CSS
它有 2 种 import 的 way.
第一是在 HTML 放 <link>
第二是在 CSS 放 @import, 我个人喜好是用这个

它其实就是一个去加载 CSS 的 URL

知识点
1. 以前是 css, 现在是 css2 版本不同了, Google 对字体做了一次改版, 如果你切换到 css 会拿到旧版本的字体
2. selected font-style
3. selcted font-weight
4. font-display 这个下面会详解讲它的作用.
如果有多个字体的话, 它的 URL 长这样

我加多了一个字体 Open Sans, 没有什么特别的. 只是 query param 多了 1 set family 而已 (相同 query param key 不常见, 但其实是符合规范的. 题外话: ASP.NET Core 获取 same query param key)
Set font-family Style
下方有声明如何使用在 Style

sans-serif 是 Roboto 的 fallback 字体.
效果

Import 的 CSS 做了什么?
上面有一个关键就是 Import CSS, 它做了啥?

用 DevTools 可以看到, 它加载了一个 CSS Style, 里面有 @font-face
@font-face
@font-face 是 CSS 语法. 用来 define 一个字体. 来看看它的属性.
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
font-family, style, weight 就不多说了.
src
字体文件 URL. 之前在 W3Schools 学习笔记 (3) – CSS Web Fonts 中有提过.
字体要渲染需要 TTF/OTF, WOFF 或者 WOFF2 文件.
所以, @font-face 只是定义了加载路径, 游览器会依据这个路径再去加载字体文件, 才能渲染.
另外, Google Fonts 是可以 self host 的哦, 通过 google-webfonts-helper 下载字体, 或者到官网下载 (but 官网的是 TTF, helper 是 WOFF2), 然后把 .woff2 或 .ttf 文件放到自己 server, src 改成 link to 自己 server 路径就可以了.
font-display
参考:
它有好几个值
auto: 依据游览器行为, 一般是 block
block: 上面说了游览器需要加载 .woff 文件, 这段期间字体要如何展现呢?
block 就是不显示. 直接给一个白色, 完全看不到字, 直到字体下载完成渲染后才显示. 这个体验叫 FOIT (Flash Of Invisible Text), 很少人这样做的, 体验不好
swap: 在等待加载的时候, 先显示 fallback 字体, 等加载完成才显示最终字体. 这个体验叫 FOUT (Flash Of Unstyled Text), 大部分人都这样做 (虽然体验也不是 100% 的好)
fallback: block 和 swap 的折中方案, 会先 block 100ms 左右, 然后 3秒 swap, 如果 3 秒后还没有加载成功, 那么就一直用 fallback 的. 考虑到 3 秒后用户已经开始阅读内容了, 这时切换字体会很明显跳一下, 体验扣很多分
optional: 和 fallback 类似. 只是把权力交给游览器依据下载速度决定是否去加载字体.
block, swap, fallback, optional 可以理解为你多在意自定义字体. block 就是一定要用自定义字体, 其它的连看都不可以. swap 就是可以先看 fallback 但最后一定要看到自定义
fallback 就不一定要看到自定义, 加载快才看. optional 顾名思义, 更加不注重了. 大部分人都会用 swap.
unicode-range 没有认真研究. 从 Google Fonts 的 @font-face 可以看到, 同一个 family, style, weight 会有很多版本的 unicode-range.
提醒:
不同 font-family, 不同 style, 不同 weight, 不同 unicode 都需要新的一个 @font-face 哦. 所以 @font-face 会有很多很多的.
CSS Font Loading API
参考:
stackoverflow – How to be notified once a web font has loaded
Medium – Getting started with CSS Font Loading
上面说到, @font-face 定义了 .woff2 的加载路径, 然后游览器去加载文件后渲染.
font-display swap 会先显示 fallback 的字体, 然后切换, 所以字体的 size 会改变.
如果我们依赖这个字体的 width 怎么办呢? 虽然可以用 ResizeObserver 监听, 但它不是最好的. 更好的是用 document.fonts
document.fonts 是一个 iterable 对象. 它记入了所有 @font-face 的内容.
for (const font of document.fonts) {
console.log("font", font);
}
遍历后可以看到所以 @font-face 定义的字体

下面 2 个监听方式
document.fonts.ready.then(() => {
console.log("all loaded");
});
[...document.fonts][0].loaded.then(() => {
console.log("specify font loaded");
});
第一个是监听所有 font 加载完毕
第二个是指定某一个 font 加载完毕
JS 动态加载 font-face
上面都是靠 CSS @font-face 去加载的. JavaScript 也是有 API 可以动态加载 font 的哦.
注释 CSS
/*
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2)
format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
*/
JavaScript
document.querySelector("button")!.addEventListener("click", () => {
// define
const robotoFontFace = new FontFace(
"Roboto",
`url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2)
format("woff2")`,
{
display: "swap",
style: "normal",
weight: "400",
unicodeRange: `U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD`,
}
);
// load
robotoFontFace.load().then(() => {
// add to document.fonts
document.fonts.add(robotoFontFace);
// set style
document.querySelector("h1")!.style.fontFamily = `Roboto`;
});
});
new FontFace 类似 CSS 的 @font-face. 照搬而已.
定义好 FontFace 把它添加到 document.fonts 里面去. 然后就可以使用了.
我上面调用 load 只是一个示范而已. 其实只要添加进了 document.fonts 它就会自动去加载了.
和 font-family 有关的文章
webpack – postcss-font-magician
总结
1. font-family 需要 .woff2 文件 (.woff2 文件就是 font 的设计文档, 有些是版权的哦, 不可以随便用)
2. CSS Style @font-face 只定义了加载路径
3. 游览器加载 font 时, font-display 控制体验
4. JS 也有 API 可以设置 font-face 和监听 font rendered.
中文 font
参考:
CSS - Tracks – System Font Stack
英文字体有非常多的选择, 电脑没有可以去下载一个就搞定了.
但中文就不行了. 中文 file 太大了, 随便一个就可能要 10mb.
所以网站要支持中文, 就只能用电脑已有的字体.
Safe fonts
下面是英文的 safe fonts

那中文呢...不好意思...没有通用的.
不同的 OS 用的中文字体是不同的, 而我们需要兼顾 4 个 OS, Windows, macOS, IOS, Android.
font-family
system-ui 这个是所有 OS 通用的字体 (比较新, 如果要兼容一些老旧设备需要配上下面几个)
-apple-system 这个是苹果机 IOS, macOS 的字体.
BlinkMacSystemFont 这个是早年的 macOS Chrome 的字体
Segoe UI for Windows
Noto Sans for Android (在 Android. Noto for chinese, Roboto for english)
full version
所以目前最常见的方案是
先放一个 english pretty 字体.
然后跟着下面这句
my-pretty-font,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"
这样就可以保证中英文都支持美美了.
各大网站参考
system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"
Inter var,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji
"PingFang SC","Microsoft YaHei","Helvetica Neue","Helvetica","Arial",sans-serif;
"Gotham SSm", "PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif
"SF Pro SC", "HanHei SC", "SF Pro Text", "Myriad Set Pro", "SF Pro Icons", "Apple Legacy Chevron", "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif
"Segoe UI",SegoeUI,"Helvetica Neue",Helvetica,Arial,sans-serif
-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"
source-serif-pro, Georgia, Cambria, "Times New Roman", Times, serif
可以看到 Boostrap, TailwindCSS, Github 是比较完整的. 像 Microsoft 根本不鸟 IOS, macOS, Apple 也没放 Segoe UI.
CSS – Font Family的更多相关文章
- 【转载】CSS font关键字属性值的简单研究
文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/wordpress/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=5 ...
- CSS Font知识整理总结
1.什么是字体 字体是文字的外在形式,就是文字的风格,是文字的外衣.比如行书.楷书.草书,都是一种字体.同样一个字每个人写起来都会有差异,可以说每个人都有一套潜在的字体库.对于web页面来说,字体就是 ...
- CSS font 复合属性的顺序
CSS 参考手册 实例 在一个声明中设置所有字体属性: p.ex1 { font:italic arial,sans-serif; } p.ex2 { font:italic bold 12px/20 ...
- CSS font字体知识学习
字体系列 [1]5种通用字体系列:拥有相似外观的字体系列 serif字体:字体成比例,且有上下短线(衬线字体),包括Times\Georgia\New century Schoolbook sans- ...
- css常用的简写技巧_css background简写、css border 简写、css font属性简写等
css样式中有很多简写方式,比如:设置背景,字体,边框,盒子等.我们都可以把css代码合并为一行,这篇文章将总结有哪些属性支持css简写. 1.背景background属性 background-co ...
- css font的简写规则
font的属性简写里面常用的有5个是可以写在一起的: font-style设定斜体 如:font-style: italic;font-weight设定文字粗细 如:font-weight: bold ...
- css font简写规则
是不是在很很多网站的公共样式中会看到这样的代码?font: 12px/150% Arial, Verdana, "\5b8b\4f53";意思为:字体大小/行高 字体族 " ...
- CSS Font文字样式
font-style: /* 文字样式 italic(倾斜) | normal */ font-weight: /* 文字是否加粗 bold | normal(正常) */ font-size: /* ...
- CSS| font property
字體屬性 常用的CSS字体名称 宋体 SimSun 黑体 SimHei 微软雅黑 Microsoft YaHei 微软正黑体 Microsoft JhengHei 新宋体 NSimSun 新细明体 P ...
- CSS font系列
font-family font-family: Verdana,Helvetica,Arial,"Microsoft YaHei",sans-serif; font-family ...
随机推荐
- adorner 使用示例
模块介绍 adorner 是一个现代轻量级的 Python 装饰器辅助模块. 目前该模块仅实现了 4 个类,对应着 4 个功能:制造装饰器.执行计时.函数缓存.捕获重试. 仓库地址:https://g ...
- leetcode简单(矩阵):[566, 766, 832, 867, 999, 1030, 1261, 1275, 1337, 1351]
目录 566. 重塑矩阵 766. 托普利茨矩阵 832. 翻转图像 867. 转置矩阵 999. 可以被一步捕获的棋子数 1030. 距离顺序排列矩阵单元格 1260. 二维网格迁移 1275. 找 ...
- 高程读后感(四)— 关于BOM本人容易忽略的知识点总结
目录 window对象 window对象上属性及方法 超时调用setTimeout和间歇调用setInterval BOM location对象及其位置操作 history对象 window对象 wi ...
- Linux 手工释放Linux Cache Memory
手工释放Linux Cache Memory 为了加速操作和减少磁盘I/O,内核通常会尽可能多地缓存内存,这部分内存就是Cache Memory(缓存内存).根据设计,包含缓存数据的页面可以按需重新用 ...
- 商业级java开发单体项目环境搭建
写在开发前,端口经常被战占,windows10用以下命令先查先杀,netstat -aon | findstr "8080" taskkill /F /PID <PID> ...
- 【SpringBoot】06 探索配置方式 Part2 占位符的使用
配置占位符? 随机数配置生成 RandomValuePropertySource 在配置文件中使用随机数 uid = ${random.value} uid = ${random.int} uid = ...
- python高性能计算:cython使用openmp并行(示例)
y.pyx import cython from cython import parallel from cython.parallel import prange cdef int i cdef i ...
- ( Ubuntu系统下 ) vim插件安装 supertab 实现tab键的补全功能 (vim+python环境下)
本文前提已经安装了 Vundle : 下载 supertab : git clone https://github.com/ervandew/supertab ~/.vim/bundle/ 编 ...
- 再探 游戏 《 2048 》 —— AI方法—— 缘起、缘灭(2) —— 游戏环境设计篇
注意: 本文为前文 再探 游戏 < 2048 > -- AI方法-- 缘起.缘灭(1) -- Firefox浏览器自动运行篇 接续篇. ========================== ...
- springboot实现事务管理
Springboot实现事务步骤1.在启动类加上@EnableTransactionManagement 2.在业务层方法上加 @Transactional(rollbackFor = Excepti ...