前端开发者学堂 - fedev.cn

Web Fonts 的优化:Web Fonts vs. 系统字体

发布于 大漠

Web Fonts 在 Web 中的使用已随处可见,比如聚划算页面中的 价格 使用的就是 Web Fonts(即 AlibabaSans102-Bd):

虽然使用 Web Fonts 能在视觉上达到更好的效果(满足设计师的需求),但对于 Web 性能是有影响的,给用户的体验也是有影响的。如果Web Fonts 未加载,浏览器通常会延迟任何使用 Web Fonts 的文本(比如聚划算的价格)。这在许多情况下,将延迟 FCP(First Contenttful Paint),在某些情况下也会延迟 LCP(Largest Contentful Paint)。甚至更为严重的是导致布局偏移(Layout Shifts),会触发页面的重排和重绘(Web Fonts 和它的备用字体或系统字体在页面上占用不同的空间), 也会触发 CLS(Cumulative Layout Shift)。更令人感到头痛的是,Web Fonts 造成布移偏移的原因是 FOUT(Flashes Of Unstyled Text),而且 FOUT 还是业内公认的难以解决的。

简单地说,Web Fonts 对视觉效果是有显著帮助,但对Web性能和用户体验是有严重影响。如果在实际业务中能避免 Web Fonts 的使用应该尽可能的不用,如果实在不能避免,那就要在使用 Web Fonts时做一些策略上的选择。接下来,我们围绕着 Web Fonts 的使用和性能优化来展开讨论。 ​

Web 排版

一直以来在 Web 上都是以 “内容为王”,其中文字内容在 Web 内容中占了很大的比例。即使是非装饰性的图片也应该在 HTML 的标记 <img> 中用文字来描述图片(alt 属性)。如果 Web 上的内容都是一段一段的文字,那么这个地方就会变得很无聊。 ​ 值得庆幸的是, Web 是一种视觉媒介,有许多机会通过 设计排版 来传达思想。多年来,设计师们急于将自定义的排版带到 Web 上,并突破“Web安全字体”的限制。在 Web 近30年的发展过程中,先后使用过 “图片替换文本”(带有艺术字体,至今也还在使用),sIFR(Scalable Inman Flash Replacement,使用Flash等价物替换屏幕上的文本元素,今天基本废弃不使用),接下来是 cufón(2017年停止服务)。但这些技术都存在一定的缺陷,甚至已不是现代 Web 开发的主流技术,哪怕现在还在使用的 “图片替换文本” 也不建议使用。比如下图就是“图片替换文本”技术在Web页面中的运用场景: ​

在现代Web开发中,我们应该使用 CSS 的 @font-face 技术来使用自定义的字体(即 Web Fonts),该技术早在 2008 年左右就出现了(最早出现在 1998年 CSS2规范中),可以让浏览器加载本地字体或放在CDN的字体:

@font-face {
    font-family: 'Alibaba Sans 102 v1 TaoBao';
    src: url('AlibabaSans102v1TaoBao-Bold.eot');
    src: url('AlibabaSans102v1TaoBao-Bold.eot?#iefix') format('embedded-opentype'),
        url('AlibabaSans102v1TaoBao-Bold.woff2') format('woff2'),
        url('AlibabaSans102v1TaoBao-Bold.woff') format('woff'),
        url('AlibabaSans102v1TaoBao-Bold.svg#AlibabaSans102v1TaoBao-Bold') format('svg');
    font-weight: bold;
    font-style: normal;
    font-display: swap;
}

CSS 的 @font-face 对于 Web 来说是一个很好的补充,它解决了上述老技术(“图片替代文本”、sIFR和cufón)中与可访问性和可维护性有关的许多问题。但是,@font-face 也带来了它自已一系列挑战。主要是不同的字体格式,以及它们的加载方式,更为麻烦的是它对Web性能和用户体验的影响。

**注意,Web安全字体(Web Safe Fonts)不等同于 Web字体(Web Fonts),其中 Web 安全字体指的是系统中(或客户端)都兼容(或大部分兼容)的字体(也是系统字体中一子集),而 Web 字体大多指的是自定义字体(具有个性化字体),也就是 @font-face 中引入(加载)的字体!

那我们就先从“系统字体与Web字体”开始聊起。

系统字体 vs. Web 字体

系统字体 是指安装在电脑上的字体,这些字体通常包含在操作系统中,但也可以与某些应用程序捆绑在一起或用户手动安装:

(上图是macOS Big Sur 系统中自带的字体和用户安装的字体,打开 Font Book APP 可查阅)

Web Fonts 一般是指存储在项目指定的目录(如 /src/assets/fonts/)或网络服务器上的字体文件,浏览器客户端或Web应用程序临时下载这些文字是为了让 Web 页面按照设计师的意图渲染文字效果。比如 Google FontsAdobe Typekit 都是著名的 Web Fonts 服务商,提供很多在线 Web Fonts:

随着 2009 年 Adobe Typekit 等服务的推出,Web Fonts 就开始流行起来。在此之前,如果设计师和 Web 开发者希望他们的 Web 页面或应用上的文字在不同的浏览器和操作系统上看起来一样,就只能使用一些“网格安全”的系统字体,比如 ArialCalibriHelveticaVerdanaCourierGeorgiaPalatinoTimes New Roman 等:

(中间黄色区域是在Widows 11 和 Mac OS12 Monnterey 两系统中的Web安全字体)

十几年过去了,Web Fonts 大行其道,而系统字体则失宠,被许多人视为无聊和缺乏想象力。但是,Web Fonts并像 Google Fonts 总是免费的,有些Web Fonts是需要花钱购买的。另外, Web Fonts 的在Web上使用也是要附出一定代价的(除了购买要钱),还会占用用户的带宽,也给 Web开发者在性能优化上(比如字体加载)带来不小的压力,而且使用 Web Fonts 还有可能引起不同方式的文本闪现(比如 FOUT、FOIT 和 FOFT)。

使用系统字体的最大好处是,它们已经存在于大多数设备上。这意味着当用户访问你的 Web 应用时,被使用的字体不需要被下载到用户的电脑上。这为用户节省了带宽,降低了加载你的 Web应用所需的请求数。再强调一次,Web Fonts 则刚好相反,大多数情况之下(除使用 Base64 URI格式字体)都需要下载才能让 Web 应用上的文字按照指定的 Web Fonts 渲染。比如 Medium.com 首页,就有多个 Web Fonts 文件被下载:

在我们讨论选择正确的 Web Fonts以及如何确保它不影响你的 Web 应用的加载时间之前,我们首先需要问自己一个问题。真的需要使用定制的 Web Fonts 吗?还是使用系统字体就足够了?正如 @David Gilbertson 所说

是否决定使用 Web Fonts,应该按“应该”或“不应该”这样一刀切的说法来决定,而是应该有某种准则来帮助你决定是否在自己的应用中使用 Web Fonts。

换句话说,是否使用 Web Fonts其底线是要问自己为什么需要使用一种 Web Fonts?尝试着按上面的规则去做选择,可能会比“应该”或“不应该”更明智。简而言之,如果 Web Fonts 给你带不任何的价值,我们应该以“系统字体优先”为原则,因为这也是一种更可持续的方法来选择字体。

系统字体的使用

众所周知,在 Web 开发中,都是通过 CSS 的 font-family 属性给文本指定一个字体或一个字体集来渲染文本,比如:

h1 {
    font-family: fell, Georgia, Cambria, "Times New Roman", Times, serif;
}

h2  {
    font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

p {
    font-family: charter, Georgia, Cambria, "Times New Roman", Times, serif;
}

font-family 非常有意思,当该属性的值是一个系列值(Font Stacks)时,客户端首先会取这个系列值中的第一个字体,如果客户端(系统)没有这个字体,那将会取第二个,依此类推。如果 font-family 属性指定的字体集都不在系统中或未显式指定字体名称,那么将会取该属性的初始值,只是其初始值是依赖于用户代理(User Agent)。

在以往给 Web 应用显式设置系统字体的时候,都会指定具体的字体名称,比如:

// Windows, Mac, iOS
font-family: Georgia, Times, Times New Roman, serif;
font-family: Palatino, Palatino Linotype, Palatino LT STD, Book Antiqua, Georgia, serif;

// Windows, Mac, iOS, Ubuntu
font-family: Charter, Bitstream Charter, serif;

// Mac, iOS
font-family: Hoefler Text, Baskerville Old Face, Garamond, Times New Roman, serif;

// 中文 Web
font-family: Georgia, "Times New Roman", "Microsoft YaHei", "微软雅黑",  STXihei, "华文细黑",  serif;

不过,自从 2020 年 8 月起,使用下面的代码来设置字体,可以在大多数平台上获得系统字体,并且有合理的回退值:

body {
    font-family: "Segoe UI",system-ui,-apple-system,sans-serif;
}

注意,代码中的关键词 **system-ui** ,在 CSS Fonts Module Level 4 规范中有 system-ui 作为 font-family 属性值的明确描述。该属性值大概在 2015 年左右出现,并在 2017 年左右得到大多数浏览器支持,特别是在 2020 年之后,这种字体的使用已经非常的普遍: ​

// Medium in 2015
font-family: -apple-system, BlinkMacSystemFont, “Segoe UI”, Roboto, Oxygen, Ubuntu, Cantarell, “Fira Sans”, “Droid Sans”, “Helvetica Neue”, sans-serif;

// WordPress in 2016
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;

// GitHub in 2017
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI”, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";

// Booking.com in 2017
font-family: -apple-system, BlinkMacSystemFont, “Segoe UI”, Roboto, Helvetica, Arial, sans-serif;

不过有一个事实,在 2019 年,当 "系统" 字体堆栈被越来越多的人使用时,实际的关键词 system-ui 却被忽略:

// GitHub
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol

// Instagram
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif

// ESPN
font: 16px -apple-system,BlinkMacSystemFont,"Roboto","Arial","Helvetica Neue","Helvetica",sans-serif;

// LinkedIn
font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue","Fira Sans",Ubuntu,Oxygen,"Oxygen Sans",Cantarell,"Droid Sans","Apple Color Emoji","Segoe UI Emoji","Segoe UI Emoji","Segoe UI Symbol","Lucida Grande",Helvetica,Arial,sans-serif;

// Wordpress Admin
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;

// Notion
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"

// Bootstrap
font-family: -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";

// Tachyons
font-family: -apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif;

// Tailwind
font-family: -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;

// Twitter
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;

从 2020 年系统字体堆栈也有着新的声音:

// Voice 1:
font-family: -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;

// Voice 2:
font-family: system, -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;

// Voice 3:
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI”, Roboto, “Helvetica Neue”, Arial, sans-serif;

// Voice 4:
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Oxygen, Cantarell, sans-serif;

// Voice 5:
font-family: Segoe UI,system-ui,-apple-system,sans-serif;

在上面这些示例代码中,可以看到不管是哪种使用方式,所谓的 系统字体堆栈中都有着相同的字体名称。这里简单地介绍一下:

  • system-ui 可以照顾到最新的浏览器和所有未来的系统字体。然而,对于使用中文排版的用户来说却适得其反(也可能对其他 Windows 系统不是 Segoe UI 用户)。如果你的用户来自全世界,包括那些母语不使用拉丁文字形的人,最好的办法可能是像 Bootstrap 那样,放弃使用 ****system-ui** 。另外,在Mac OS 和 iOS 系统上,system-ui 指向的中文字体为“苹方”(PingFang SC),西文是 San Francisco;Android系统下中文常是 Noto Sans (思源黑体),西文是 Roboto ;Windows 系统一般是微软雅黑(Microsoft YaHei
  • -apply-system 用于 Mac OS 和 iOS 上旧版本的 Safari 浏览器。这里的前缀 -apply 是苹果供应商独有的私有前缀,为此也有人建议在 -apply-system 前面添加一个不带前缀的 system 关键词
  • BlinkMacSystemFont 适用于 Mac OS 和 iOS 上旧版本的 Chrome 浏览器
  • Segoe UI 适用于 Windows 7 或更高版本的所有浏览器
  • Roboto 适用于 Android 和 Chrome OS。Github网站省略了 Roboto ,因为它在 Linux 的一些发行版会引起问题,这些“问题”到今天可能已经解决,也可能还未解决。如果 Linux 用户对你的网站来说是不可忽视的用户群体,那么建议你也请忽略 Roboto 。与西文 Roboto 对应的中文字体是“思源黑体”,即 Noto Sans
  • San Francisco 是 2017 年苹果公司的 Mac OS 10.11 和 iOS 9 发布的,相比于 Helvetica 字体,San Francisco 的字体网格更加简洁。但 San Francisco 字体有点神奇,在安装的时候会变成 .SFNSText-Regular ,如果你需要使用 San Francisco 字体的话,千万别忘了在它前面加上 .SFNSText-Regular
  • Helvetica Neue 用于 Mac OS 10.10(Yosemite)上的旧浏览器。另外 Medium 和 WordPress 也建议忽略 Mac OS 10.9 的系统字体(Lucida Grande),因为 Mac OS 长期以来一直是使用 Helvetica Neue
  • Arial 用于非常老的 Windows
  • sans-serif 用于最后的手段(回退值),适用于旧的浏览器。实际上,只要用户没有安装 Segoe UIRobotoHelvetica NeueArial 字体,它可以处理 Linux 系统字体
  • 如果你的网站有一些表情符号,那可以在最后添加 Apple Color EmojiSegoe UI EmojiSego UI Symbol ,其中 Sego UI Symbol 是 Windows 7 和 8 的回退值,因为 Segoe UI Emoji 是与 Windows 10 一起发布的

虽然说 system-ui 可以自由的匹配系统字体(不同操作系统不同浏览器客户端),但并不意味着你可以直接在代码中使用 font-family: system-ui 。不过,依赖于 PostCSS的插件,比如 postcss-preset-env 的话,可以直接这样使用,因为编译的时候会自动编译出更符合系统字体的代码:

// input.css
body {
    font-family: system-ui;
}

// output.css
body {
    font-family: system-ui, -apple-system, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue;
}

注意,使用 postcss-preset-env 插件将 system-ui 编译出来的“系统”字体堆栈(系统字体集)有可能不能满足你的字体需求。如果是这样的话,请甚用!

系统字体对于 Web 开发者来说,是容易的也是复杂的。为什么这么说呢?因为我们在拿到设计稿的时候,时常只是针对一个系统中的字体,更多的只是 Mac OS 系统下的字体。因为设计师大多数都是基于Mac OS 系统做的设计,就目前为止更多会指定字体为 “苹方简”,即 PingFang SC

但“苹方简”只存在于 Mac OS系统上。换句说,如果只是显式指定 font-family: "PingFang SC" 时,在别的系统下看到的不一定是苹方,比如在安卓系统上,它可以看到的是“思源黑体”(Noto Sans)。所以我们在指定 font-family 属性值(使用字体)需要一些规则:

  • 西文字体在前,中文字体在后:一般情况之下,中文字体大多都包含西文,但西文的部分不太好看;而西文字体不一定包含中文。因此,通常先定义西文,后定义中文以达到更优的显示效果
  • 优先使用 system-uisystem-ui 会使用当前系统的默认字体,让Web 页面或应用与操作系统的字体网格统一,体验更好
  • 兼容不同的操作系统:选择字体时要考虑不同的操作系统,还需要考虑旧版本操作系统用户。即便同一字体在不同的操作系统下也会有略微差异,我们应该尽可能的做到相同系统使用同一种字体,保证同一系统下的字体一致性。对于不同系统尽量保证字体网格接近,比如使用无衬线字体(sans-serif)。如果你的用户群体大部分是中文用户的话,为了保证Mac OS 和 iOS 系统使用更优雅的中文字体,首先是“苹方简”(PingFang SC),对于不支持苹方的低版本 Mac OS 和 iOS 应该考虑使用 "冬青黑体"(Hiragino Sans GB)兜底。如果还需要兼容 Linux 系统中文用户,则要添加“文泉驿微米黑”(WenQuanYi Micro Hei)。 Windows 系统中文更多使用的是“微软雅黑”(Microsoft Yahei
  • serifsans-serif 作为备用字体,一般将 sans-serif 放在字体堆栈最末尾
  • 简洁实用:并不是字体设置的越多越实用,我们应该在能满足设计需求的情况下尽量简洁。相同系统下中西文字体各有一个备用字体(Fallback Font)即可

不同系统字体的使用建议:

  • 英文和数字部分:在默认的操作系统中,Mac OS 和 Windows 都会带有 ArialVerdanaTahoma 等几个预安装字体,从显示效果来看,Tahoma 要比 Arial 更加清晰一些,因此在设置字体时,Tahoma 最好放置在最前面,当找不到 Tahoma 时再使用 Arial ;在 Mac 系统中 Helvetical 能给 Mac用户带来更好的体验;安卓系统下默认无衬线体(一般是 Roboto)就可以接受,无需单独设置,如果需要单独设置,可以考虑 Roboto 。最后,英文和数字字体最佳写法是:font-family: Helvetical, Tahoma, Arial;
  • **中文部分:**在Window系统,“微软雅黑”(Microsoft Yahei)是最常使用的中文字体;Mac 系统中更优雅的中文字体设置是 “苹方”(PingFang SC)、“黑体简”(Heiti SC)、“冬青黑体”(Hiragino Sans GB);如果还需要考虑 Linux 系统的中文体验的话,就还要添加 “文泉驿微米黑”(WenQuanYi Micro Hei)。最后,中文字体部分最佳写法是:font-family: "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft Yahei", "WenQuanYI Micro Hei";

这样我们可以得到一个较佳的系统字体使用方式:

// 仅英文和数字
font-family: "Segoe UI", system-ui,-apple-system,sans-serif;

// 仅英文和数字向下兼容
font-family: "Segoe UI", system-ui, -apply-system, BlinkMacSystemFont, Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";

// 仅中文
font-family:system-ui, -apply-system, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;

// 可以考虑加入华文细黑 STXihei 和黑体 SimHei
font-family: system-ui, -apply-system,"PingFang SC", "Hiragino Sans GB", "Heiti SC", STXihei, "Microsoft YaHei", SimHei, "WenQuanYi Micro Hei", sans-serif;

// 中英文混合
font-family: "Segoe UI", -apply-system, BlinkMacSystemFont, Roboto,"Helvetica Neue",Arial,"Noto Sans","PingFang SC", "Hiragino Sans GB", "Heiti SC", STXihei, "Microsoft YaHei", SimHei, "WenQuanYi Micro Hei",sans-serif,

另外,再花一点点时间看看主流一些网站使用了哪些系统字体:

// Twitter
font-family: TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

// Facebook
font-family:system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif;

// Github
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";

// Youtube
font-family: Roboto, Arial, sans-serif;

// Google
font-family: Roboto,Helvetica Neue,Arial,sans-serif;

// Medium
font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-family: charter, Georgia, Cambria, "Times New Roman", Times, serif

// Amazon
font-family: "Amazon Ember",Arial,sans-serif;

// Amazon CN
font-family: 'Hiragino Sans GB','Microsoft Yahei',Arial,sans-serif;

// JD
font-family: -apple-system,Helvetica,sans-serif;

// PDD
font-family: -apple-system-font,"Helvetica Neue",sans-serif;

// Baidu
font-family: Arial,Helvetica,sans-serif;

// Toutiao
font-family: SF Pro Display,PingFang SC,Hiragino Sans GB,Microsoft YaHei,WenQuanYi Micro Hei,Helvetica Neue,Arial,sans-serif;

// 腾讯新闻
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Microsoft Yahei", sans-serif;

// QQ
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Microsoft Yahei", sans-serif;

// Weixin
font-family: -apple-system-font,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei UI,Microsoft YaHei,Arial,sans-serif;

// Weibo
font-family: Helvetica Neue,Helvetica,Arial,sans-serif;

// 网易新闻
font-family: PingFangSC-Regular,Microsoft YaHei,Helvetica;

// 网易云音乐
font-family: Helvetica,sans-serif,STHeiTi;

// 聚划算
font-family: Helvetica,sans-serif;

// 淘宝 PC
font-family: tahoma,arial,'Hiragino Sans GB','\5b8b\4f53',sans-serif;

// 小米
font-family: "Helvetica Neue",Helvetica,Arial,"Microsoft Yahei","Hiragino Sans GB","HeitiSC","WenQuanYi Micro Hei",sans-serif;

// CSS-TRICK
font-family: Blanco,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;

// smashingmagazine
font-family: -apple-system,BlinkMacSystemFont,Arial,sans-serif;

// 掘金
font-family: -apple-system,system-ui,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial;

// 知乎
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;

CSS 的 font-family 是可以用于任何 HTML 元素上的,而且它是一个可继承的属性。在 Web 开发过程中,设置系统字体一般都是将其设置为一个全局的字体。在编码的时候,可以像下面这样来设置:

html {
    font-family: "Segoe UI", -apply-system, BlinkMacSystemFont, Roboto,"Helvetica Neue",Arial,"Noto Sans","PingFang SC", "Hiragino Sans GB", "Heiti SC", STXihei, "Microsoft YaHei", SimHei, "WenQuanYi Micro Hei",sans-serif,
}

如果在某个元素上,希望设置另外的字体,我们可以在具体元素上重置 font-family 值,比如:

.price {
    font-family: "Alibaba Sans 102 v1 TaoBao";
}

有关于系统字体的使用就先介绍到这。如果你想更深入了解系统字体,建议花点时间阅读下面这几篇文章:

Web Fonts的使用

Web Fonts 指的是用户自定义字体(一般是设计师单独设计的字体)或个性化字体,它和系统字体最大的差异是“Web中使用需要先下载”。对于 Web 开发者而言,需要先使用 CSS 的 @font-face 属性将 Web Fonts 嵌入到 Web中

@font-face {
    font-family: FontName;
    src: url('path/filename.eot');
    src: url('path/filename.eot?#iefix') format('embedded-opentype'),
        url('path/filename.woff2') format('woff2'), 
        url('path/filename.woff') format('woff'),
        url('path/filename.ttf') format('truetype');
}

如果我们只想支持现代浏览器,可以只将 woffwoff2 字体嵌入到 Web中:

@font-face {
    font-family: FontName;
    src: url('path/filename.woff2') format('woff2'), 
        url('path/filename.woff') format('woff');
}

注意,使用 @font-face 只是仅仅把所需要的 Web Font (比如上面示例中的 FontName)引入到 Web中,告诉用户你在 Web 开发中可以给元素使用 FontName 字体。同样的,如果要给元素使用指定的 Web Font,就需要在该元素上显式的指定 font-family 属性的值是你引入的 Web Font:

.font-name {
    font-family: FontName;
}

只有这样,浏览器才知道在什么时候,什么地方使用 FontName

上面这种方式是引用存放在本地项目中或托管在自己 CDN 上的 Web Font。如果你使用像 Google Fonts 服务商提供的 Web Fonts的话,可以直接通过 <link> 标签引入:

<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet">

相当于引入了个 .css 文件。当你尝试着打开 href 指定的字体链接时,你可以看到该 CSS 文件中也是使用 @font-face 将 Web Fonts 嵌入到 Web中:

正如上图所示,你可以将所需的 Web Fonts 放在同一个 CSS 文件中,而且每一个 @font-face 对应的是一个 Web Font。更有意思的是,如果你只是在 .css 中使用 @font-face 将 Web Font 嵌入到 Web 中,但没有被任何元素的 font-family 引用的话,该字体是不会被浏览器下载的。我们来看下面这个示例:

// 使用 @font-face 将 AlibabaSans102 字体嵌入到 Web中

@font-face {
    font-family: AlibabaSans102;
    src:
        url('/font/AlibabaSans102.woff2') format('woff2'),
        url('/font/AlibabaSans102.woff') format('woff'),
        url('/font/AlibabaSans102.ttf') format('truetype');
}

如果 h1 元素未显式设置的 font-family 或显式设置 font-family 为系统字体(非 Web Font),浏览器瀑布图“字体”项中是空的,没有任何字体文件加载(下图左侧);反之,在 h1font-family 值引用了 @font-face 嵌入的 AlibabaSans102 字体,比如 font-family: AlibabaSans102 ,那么浏览器会根据自己所需下载相应的 AlibabaSans102对应的字体文件(下图右侧,Chrome 浏览器下载了 AlibabaSans102.woff2):

从这个示例中不难发现:

@font-face 嵌入的字体,只要没有被元素的 font-family 属性引用,浏览器是不会下载 @font-face 嵌入的字体文件!

Web Fonts 的使用就是这么简单,它不用像使用系统字体那样,考虑不同平台,不同系统的兼容性。因为浏览器会将被引用的 Web Fonts 对应的字体文件下载下来,也就没有字体不存在一说。只不过在使用 Web Fonts 时,需要提供不同的字体格式。

字体格式

@font-facesrc 引入字体的时候有一个重要参数 format(<font-format>) ,用来指定嵌入字体的格式:

可以看到不同的 <font-format> 值对应着不同的字体格式,比如 EOTTTFWOFFWOFF2SVG 等。不幸运的是,尽管字体格式种类繁多,但没有哪一种格式可以在所有浏览器中使用。这就意味着,你必须使用多种字体格式来给用户提供一个一致的体验:

上图中所列的就是 Web Fonts 常见的字体格式。你在购买 Web Fonts 时收到的字体文件包,通常至少包括这些字体格式,即使你自己设计字体的时候,也至少应该提供这些字体格式。

我们简单的来了解一下这几种字体格式:

  • TTF(TrueType Font):TTF 字体格式是由苹果和微软为 PostScript 而开发的字体格式。在 Mac 和 Windows 系统上,TTF一直是最常见的字体格式,所有主流浏览器都支持它。如果你要在 IE8 及其以下的浏览器使用,那还是考虑放弃吧,即使是 IE9 也是要被设置为 “Installable” 才能支持。其最大的缺点就是 字体没有被压缩,文件较大
  • OTF(OpenType Font):由 TTF 演化而来,是 Adobe 和微软共同努力的结果。OTF 字体包含一部分屏幕和打印机字体数据。OTF 有几个独特功能,包括支持多平台和扩展字符集。OTF 字体可以在 Macintosh 和 Windows 系统上使用。OTF 也允许多达 65000 个字符的存储。这个额外的空间让设计师可以自由地添加附加元素,比如小帽子、老式数字体、代替的字符和其他一些以前必须作为独立字体分发的附加材料
  • EOT(Embedded OpenType Font):EOT 字体是微软设计的,主要用于 Web 上的一种字体。是一个在 Web 页面上试图绕过 TTF 和 OTF 版权的方案。你可以使用微软的工具(一款需要附费的工具,也可以使用免费的 OTF-to-EOT工具),将现有的 TTF 、 OTF 字体格式转换成 EOT 字体格式。转换出来的 EOT 字体会得到相应的压缩和裁剪,使得 EOT 字体文件更小。同时为了避免一些受版权保护的字体被随意复制,EOT 还集成了一些特性来阻止复制行为,以及对字体文件进行加密保护
  • WOFF(Web Open Font Format):WOFF本质上是 metadata + 基于 SFNT 的字体(如 TTF、OTF 或其他开放字体格式)。WOFF 格式是为Web而生的,由 Mozilla 基金会、微软和Opera软件公司合作推出。WOFF 格式字体均经过 WOFF 的编码工具压缩,文件大小一般比 TTF 格式字体小 40% ,加载速度更快,可以更好的嵌入到 Web 页面中。metadata 允许在字体文件中包含许可数据,以解决版权问题。这是万维网联盟提倡的一种字体格式,将会成为一种主流的字体格式。目前主流浏览器的新版本几乎都支持 WOFF。WOFF 的下一代格式是 WOFF2 ,WOFF2 格式在原有的基础上提升了 30% 的压缩率。只不过 WOFF2 还没有完全得到广泛的支持,但它应该会成为下一代 Web 上更受欢迎的字体格式
  • SVG(Scalable Vector Graphics Font):SVG字体格式使用 SVG 的字体元素(<font>)定义。这些字体包含作为标准 SVG 元素和属性的字形轮廓,就像映像中的单个矢量对象一样。SVG 字体最大的缺点是缺少字体提示(font-hinting)。字体提示是渲染小字体时为了质量和清晰度额外嵌入的信息。同时,SVG对文本(body text)支持并不是特别好。因为 SVG 的文本选择(text selection) 目前在 Safari、Safari Mobile 和 Chrome 的一些版本上完全崩坏,所以你不能选择单个字符、单词或任何自定义选项,你只能选择整行或段落文本

如果你的目标是使用现代浏览器的用户,你可以使用 @font-face 的渐进方法,只提供 WOFFWOFF2 格式。这两种字体格式提供了 最好的压缩,并允许你在代码中处理更少文件。如果你想尽可能地扩大支持范围,那么就把 EOTTTF 格式加入到 @font-face 组合中。事实上,你完全可以不再需要考虑TTF (因为IE9即将跪了)和 SVG (Chrome 已经完全取消了对这种字体格式的支持)。

简单地说:

**除非你需要支持 IE8,否则你不需要考虑 WOFF 和 WOFF2 之外的字体格式;如果你不需要支持 IE11,那只使用 WOFF2 字体格式即可!**​

如何获取 Web Fonts

要在 Web 上使用 Web Fonts 就需要有相应的字体文件。字体文件的获取途径有很多,比如说在一些字体服务商平台(如 Google FontsFonts QuirrelAdobe FontsTypetogether等)上寻找自己需要的字体风格。只不使用字体服务端提供的字体,需要注意版权,另外有些字体是需要付费的。其实,在自己负责的项目中使用 Web Fonts时,字体文件更多的是来自于自己团队的设计师,他们会给你提供所需的字体文件。当然,如果你懂设计的话,你也可以自己设计字体:

字体格式转换

虽然在字体服务端或自己的设计师手上我们可以获取 Web Fonts 所需的所有字体格式(比如.eot.ttf.svg.woff.woff2),但很多时候我们可能只有 .eot.ttf.svg.woff.woff2 其中一种格式的字体文件。就我个人经验来看,更多时候拿到的是 .ttf 格式的字体文件。这样一来,我们就需要在已有的字体格式上转换(或生成)其他对应的字体格式文件。比如说在 .ttf 基础上转换(或生成)出 .eot.svg.woff.woff2 格式字体文件。只不,当下只需要 .woff.woff2 格式字体就能满足我们的需要。

我们可以使用一些在线的字体格式的转换工具(比如 TransfonterOnline Font Converter)来帮助我们快速的转换出所需的字体格式。拿 Online Font Converter 字体转换工具举例,你可以按下面这个视频的操作步骤把转换字体格式: ​

正如视频所示,把本地的一个名为 AlibabaSans102_v1_TaoBao-Bd.ttf ,经过 Online Font Converter 转换工具,转换出 .eot.ttf.svg.woff.woff2 格式的字体文件: ​

同时还会生成一个 font.css

@font-face {
    font-family: 'AlibabaSans102_v1_TaoBao-Bd';
    src: url('AlibabaSans102_v1_TaoBao-Bd.eot');
    src: url('AlibabaSans102_v1_TaoBao-Bd.eot?#iefix') format('embedded-opentype'),
        url('AlibabaSans102_v1_TaoBao-Bd.woff2') format('woff2');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'AlibabaSans102v1TaoBao-Bold';
    src: url('AlibabaSans102v1TaoBao-Bold.svg#AlibabaSans102v1TaoBao-Bold') format('svg'),
        url('AlibabaSans102v1TaoBao-Bold.ttf') format('truetype'),
        url('AlibabaSans102v1TaoBao-Bold.woff') format('woff');
    font-weight: normal;
    font-style: normal;
}

只不过和你预期的略有差异,甚至需要手动稍作调整:

注意,不同的转换工具,操作相似,但结果可能会略有差异。同样的,使用 Transfonter 来转换 AlibabaSans102_v1_TaoBao-Bd.ttf ,结果如下:

除了使用在线转换工具之外,还可以使用 Fonttools 库,在本地命令终端上做字体格式的转换。