图解CSS: 变量字体

发布于 大漠

Web排版和传统的印刷排版之间的差距不是一点点,而且Web排版一直以来都令Web开发者感到头痛,由其是Web中的字体。或许你在平时开发Web页面或Web应用的时候已经发现在Web上需要渲染一些更具艺术风格的字体,或者希望在响应式Web排版的设计中让文字能根据断点做出相应的响应等。虽然通过一些技术手段可以实现类似的效果,但同时也会造成许多新的问题产生。幸运的是,2015年开始推出了OpenType字体格式,以一些非常显著的方式改变了开发者面临的实际困难。他们有能力在较小的文件下为Web带来更丰富的排版性,但随着新的可能性和优势,新的挑战和复杂性也随之出现。那么,OpenType字体的引入之后会给Web带来什么样的变化?我们又应该在Web中怎么使用?接下来,我们一起来探讨这方面的话题。

什么是可变字体?

可变字体是数字时代的一种字体技术@John Hudson对可变字体是这样解说的

可变字体文件是一种字体文件,它的行为类似于多种字体

传统上,大多数网站使用的字体都属性同一字体族。每种字体都存储在一个单独的文件中,并具有一组独特的属性,比如字宽字重样式。现在,在一个OpenType变量字体文件中,可以存储多种字体样式,也就是说,可变字体将字体所有这些变化都存储在一个字体文件中,并且字体的大小相对较小。与静态字体相比,可变字体允许你在一个范围内使用字体的字宽、字重和样式等。

例如,大多数字体族都包含一组字体,这些字体具有100~900的不同字重。可变字体提供了在指定范围内使用任何字重的能力。因此,如果在你的网站上使用font-weight: 700是一个最佳的效果,那么你就可以使用字重为700的字体。

另外一点就是,可变字体文件要比静态字体文件小得多,这是因为可变字体中每个字符只有一个结构。构建此结构的点具有可操作性,比如可以移动这些点,从而创建出另一个权重的指令。然后插入各个样式,这意味着它们是在浏览器内动态绘制的。这也使得在半粗体和粗体之间生成不同的样式成为可能。

如果你感兴趣的话,还可以点击这里查看

插值可以在不同的轴上发生变化,比如字重的轴上。这样可以创造一个具有层次感的字体样式。还有一些命名的实例,比如regularfont-weight: 700,都可以工作,但你还可以选择两者之间的任何设计。

可变字体可以包含多个轴。你可以添加一个字宽的轴到字重轴上,并获得更多的风格。由@Dalton Maag设计的Venn,在这些例子中使用的可变字体,支持300~800的字重和75%~125%的字宽。这意味着,如果你把这些范围(500×50)相乘,就可以得到25000种风格的Venn,而且文件大小约112kb,这已经是非常完美了。

在可变字体中,常见的“注册轴”有:字宽(width字重(weight斜度(slant、**斜体(italic光学尺寸(optical size)**等,但注册轴是可以扩展的,这样设计师可以定义他们自己所需的自定义轴,并允许他们想要创建的任何类型的变化。

如何处理可变字体?

可变字体的处理主要取决于字体的设计。类型设计器提供了各种轴,这些轴描述了哪些属性是可变的,以及这些属性的允许范围。可变字体可以有两种类型的轴:注册轴自定义轴

注册轴是最常见的轴,并且是显式定义的。在可变字体设计中有五个注册轴,包括字重、字宽、斜体、倾斜和光学尺寸。每个注册轴都有一个对应的四个字母的标记,可以映射到现有的CSS属性。

注册轴 字母标记 CSS属性
Weight wght font-weight
Width wdth font-stretch
Italic ital font-style
Slant slnt font-style
Optical Size opsz font-optical-sizing

注意:注册轴不是必须的特性。包含哪些注册轴主要取决于字体设计器

除了注册轴之外,字体设计器还可以包含自定义轴。自定义轴让可变字体变得更具创造性,因为不限制自定义轴的范围、定义或数量。与注册轴类似,自定义轴具有相应的四个字母标记。但是,自定义轴的字母标记必须是大写的。例如,你定义了一个注册轴是grade,其对应的字母标记是 GRAD

接下来,我们来看看这五个已注册的轴以及如何使用它们。

字重(Weight)

五个注册轴中可能属字重最明显,几乎所有的字体都至少设计普通(Regular)和粗体(Bold),而且还有像更轻(Lighter)、更薄(Thinner)和更粗(Bolder)等极端现象。对于可变字体,可以使用CSS的font-weight属性提供一个介于为字体定义的最小值和最大值之间的数字,而不仅仅是一个关键词(比如normalbold)。根据OpenType规范,对于任何给定的字体,400对应的是normal,但是在实践中,你将看到目前它可以根据字体的不同而有很大的变化。

p {
    font-weight: 425;
}
strong {
    font-weight: 675;
}

如果要使用变化轴,就需要使用CSS的font-variation-settings属性。比如像下面这样使用:

:root {
    --text-vf-wght: 400; 
}

p {
    font-variation-settings: "wght" var(--text-vf-wght);
}

在上面折例子中,wght对应的是CSS的font-weight,而var(--text-vf-wght)是其值,即400

字宽(Width)

字体设计的另一个常见变化是字宽。它通常被称为压缩(Condensed)或扩展(Expanded)。根据相关规范可得知,100对应的是normal字宽,其有效值是1~1000。和字体权重(字重)类似,在CSS中也有相应的标准属性font-stretch,并以百分比的形式表示。在早期阶段,许多类型设计人员不一定遵守这个标准的数值范围,所以在CSS中看起来有点奇怪。但是3%~5%的范围仍然有效的,即使在这种情况下,5%实际上是正常的宽度。

在Web的使用中,可以像字宽类似有两种方式。第一种是使用CSS标准属性font-stretch

p {
    font-stretch: 89%;
}

也可以像下面这样使用font-variation-settings属性:

:root {
    --text-vf-wdth: 95;
}

p {
    font-variation-settings: 'wdth' var(--text-vf-wdth);
}

斜体(Italic)

有的时候一些字体是不包含斜体风格的类型,但这种类型有的时候却又或多或少有所需。在大多数情况下,它是一个布尔值01。通常小写字母ag的斜体形式略有不同。虽然有可能有一个范围,而不是严格意义上的01,但关闭或打开场景可能是你遇到的最常见的情况。不幸的是,尽管它的目的是和CSS的font-style:italic相匹配,但这是浏览器尚未完全实现的一个方面,因此我们不得不依赖font-variation-settings属性。

:root {
    --text-ital: 0;
}

body {
    font-variation-settings: 'ital' var(--text-ital);
}

em {
    --text-ital: 1;
}

倾斜(Slant)

可变字体中倾斜轴类似于斜体,但在两个关键方面有所不同。首先,它在一个角度范围内做倾斜,根据OpenType规范,这个角度的范围应该是“大于-90且小于+90”,其次,它不包括字形替换。通常与无衬线字体设计相关,它允许指定范围内的任何值。如果你使用的字体只有一个倾斜轴,没有斜体,你也可以使用CSS的font-style,就像下面这样:

em {
    font-style: oblique 12deg;
}

如果两个轴都有(倾斜轴和斜体轴),则需要使用font-variation-settings属性:

:root {
    --text-slnt: 0;
}
body {
    font-variation-settings: 'slnt' var(--text-slnt);
}
em {
    --text-slnt: 12;
}

光学尺寸(Optical Size)

光学上色是印刷设计的一个概念,它的目标是在小字体上达到最佳的可读性,在大字体上达到最佳的个性化。在金属字体时代,一切都是为特定的字体大小而优化的。通过数字化,你可以创造出一个适合所有尺寸的设计结果却丢失了。现在它又重新回到可变字体中。例如,小字体的笔画可能会更粗,这意味着有更少的对比,同时让文本更易读;另一方面,在更大的尺寸上,可以看到更多的细节,因此有更多的对比度。这种变化可以逐渐发生,再一次,只有一个字体文件被使用。

在可变字体中,这个轴的数值应该与font-size相匹配,并引入了一个新的CSS属性font-optical-sizing,该属性的默认值是auto。你也可以强制关闭它,或者可以使用font-variation-settings属性显式设置值。

body {
    font-optical-sizing: auto;
}

或者:

:root {
    --text-opsz: 16;
}
body {
    font-variation-settings: 'opsz' var(--text-opsz);
}
h1 {
    --text-opsz: 48;
    font-size: 3em;
}

自定义轴

可变字体到目前为止只有五个注册轴,但是类型设计器也可以创建它们自己的轴。字体设计的任何方面都可能成为一个轴。比如衬线字体(serif)或小写x字母的高度(x-height),以及其他更具创意的方面,比如重图片。

我们来看一个示例。字体的“等级”(grade)概念,其最初只是为了补尝不同类型的纸张和印刷机上的油墨增益,从而在视觉上纠正不同的工作流程,并使每个人都能看到相同的字体。其概念是在不改变间距的情况下改变字体的重量(Weight)。将其作为一个变量轴在很多方面都很有用。创建一个高对比度模式,使文本变得更重,而不需要重新流动,可以使文本在线线较暗的情况下或在设计暗黑模式时更清晰。另外在响应分辨率较低的屏幕时,它也可以派上用场,因为在低分辨率屏幕上,类型很容易变得有点细长。

在使用自定义轴时,四个字母需要使用大写方式。比如:

:root {
    --text-GRAD: 0;
}
body {
    font-variation-settings: 'GRAD' var(--text-GRAD);
}
body.dark {
    --text-GRAD: 0.5;
}

运用多个注册轴

如果可变字体同时具备多个注册轴,那么我们在实际使用的时候,可以使用font-variation-settings来同时在文本上运用,比如像下面这样:

:root {
    --text-vf-wght: 400;  
    --text-vf-wdth: 95;
    --text-vf-slnt: 9;
    --text-vf-ital: 0;
    --text-vf-opsz: 80;
}

p {
    font-variation-settings:"wght" var(--text-vf-wght), "wdth" var(--text-vf-wdth), "slnt" calc( var(--text-vf-slnt) * -1), "ital" var(--text-vf-ital), "opsz" var(--text-vf-opsz);
}

效果如下:

前面也提到过了,可变字体已知的五个注册轴有相应的标准CSS属性支持,比如:

p {
    font-variation-settings:"wght" var(--text-vf-wght), "wdth" var(--text-vf-wdth), "slnt" calc( var(--text-vf-slnt) * -1), "ital" var(--text-vf-ital), "opsz" var(--text-vf-opsz);
}

也可以写成:

p {
    font-weight: var(--text-vf-wght); // 对应“wght”注册轴
    font-stretch: calc(var(--text-vf-wdth) * 1%); // 对应的是"wdth"注册轴
    font-style: oblique calc(var(--text-vf-slnt) * 1deg); //对应的是"slnt"注册轴
    font-style: italic; // 对应的是"ital"注册轴
    font-optical-sizing: auto; //对应的是"opsz"注册轴
}

注意,按照CSS的样式规则,如果同一代码块中有相同的CSS属性,那么后者将会替代前者。而且font-style:italic在不同的浏览器下以及不同的字体之间效果都有一定的差异。如果你使用可变字体,建议是代码中使用font-variation-settings更妥当一些。

同时,在可变字体中很多注册轴都有一个区间值,比如上面示例中的wght它的区间是100~700slnt的区间是0~15,在CSS的属性运用中,可以同时赋两个值,第一个是最低值,第二个是最高值。因此,看到像下面这样的代码无需感到惊奇:

@font-face {
    font-family: 'MyVariableFontName';
    src: 
        'path/to/font/file/myvariablefont.woff2' format('woff2-variations');
    font-weight: 100 700;
    font-stretch: 85% 100%;
    font-style: oblique 0deg 15deg
}

注意:font-variation-settings属性是 CSS Fonts Module Level 4 规范中一个新特性,如果你对该属性感兴趣的话,还可以阅读《字体变体font-variation-*》一文。

可变颜色字体

可变颜色字体是一种较新的技术,有很多东西值得我们探索。在这里不会对可变颜色字体做深入的介绍,只是在此抛砖引玉,感兴趣的同学可以自行探讨。

可变颜色字体是什么呢?在解释之前,先上张图:

看到上图是不是觉得很神奇。

上图的效果就是我们所要说的可变颜色字体,即可变字体是一种带有彩色形状或图标的定制字体。来个小示例:

如果你对可变颜色字体感兴趣的话,可以阅读下面这些文章:

另外, @shadeed9的《Creating a Variable Color Font From Scratch》一文中有一节内容专门介绍了可变颜色字体,以及用一个简单的Demo,介绍了如何制作可变颜色字体。

如何在Web上使用可变字体

通过前面的介绍,我们对可变字体有了一定的了解,接下来通过实例向大家介绍如何在Web中使用可变字体。

Step01:查找可用的可变字体

可变字体相对来说是一项较新的技术,而且可变字体是一种特定的字体。所以在Web中使用可变字体时需要先确认该字体是不是可变字体。如果你自己没有可变字体,而又想体验一下可变字体相关技术,那么@Nick Sherman的 **v-fonts.com**是一个不错的选择。在这个网站上你可以找到很多可用的可变字体,而且还是开源的。另外@Indra Kupferschmid还整理了一份可变字体列表,你也可以从这里获取。

除些之外,Google Fonts提供了很多可变字体,你只需要在Google Fonts页面中搜索时选择“Show only variable fonts”选项,那么过滤出来的字体都是可变字体:

当你在右上角选择带有“Variable”标签的字体时,你将在样式列表的底部找到可变字体版本:

接下来创建自定义样式,在页面中你就可以获取到嵌入Web页面的代码:

代码如下:

<link href="https://fonts.googleapis.com/css2?family=Oswald:wght@200;300;400;469;500;600;681;700&display=swap" rel="stylesheet">

你可以根据自己的需要去自定义样式,比如wght(即font-weight)的值。

Step02: 在样式表中集成可变字体

正如第一步所示,如果你使用的是Google Fonts,你最终可以获取到一个<link>标签,同时指定了你所需要的字体以及你自定义的相关参数,比如:

<link href="https://fonts.googleapis.com/css2?family=Oswald:wght@200;300;400;469;500;600;681;700&display=swap" rel="stylesheet">

除了<link>方式之外,还可以是CSS的@import方式:

<style>
    @import url('https://fonts.googleapis.com/css2?family=Oswald:wght@200;300;400;469;500;600;681;700&display=swap');
</style>

这样你在CSS中就可以使用Oswald这个可变字体:

p {
    font-family: 'Oswald';
    font-weight: 681;
}

对于可变字体的集成并不是件复杂的事情,你可以尝试着在浏览器的地址栏粘贴下面这段代码:

https://fonts.googleapis.com/css2?family=Oswald:wght@200;300;400;469;500;600;681;700&display=swap

你会发现对应的代码中都是@font-face代码块。不同的是,指定可变字体时,@font-face和以往我们使用的方式略有不同。比如我们以往使用@font-face可能会像下面这样

@font-face {
    font-family: 'YourWebFontName';
    src: url('YourWebFontName.eot'); /* IE9 Compat Modes */
    src: url('YourWebFontName.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
         url('YourWebFontName.woff') format('woff'), /* Modern Browsers */
         url('YourWebFontName.ttf')  format('truetype'), /* Safari, Android, iOS */
         url('YourWebFontName.svg#YourWebFontName') format('svg'); /* Legacy iOS */

}

在引用可变字体时,@font-face像下面这样:

@font-face {
    font-family: "Family Name";
    src: url("YourVariableFontName.woff2")
        format("woff2 supports variations"), url("YourVariableFontName.woff2")
        format("woff2-variations");
    font-weight: [low] [high];
    font-stretch: [low]% [high]%;
    font-style: oblique [low]deg [high]deg;
}

你可能已经注意到的第一个不同之处就是srcsrc指向了同一个字体文件,这主要是@font-face的语法规则做出了调整,只不过目前有些浏览器还没有跟进而以。这种语法相对来说更为灵活了,因为我们除了可变字体之外,可能还会使用可变颜色字体。因此第一个入口使用woff2 supports variations的格式化(format)参数来指定支持两种(可变字体和可变颜色字体)字体。一旦浏览器理解了这种语法,它们就会停止解析src行。现在,他们将跳过这一步,使用woff2-variations格式来实现第二步,所有当前支持可变字体的浏览器都能理解这一点。

对于font-weightfont-stretchfont-style等属性为什么这样指定值,在前面已经有介绍,这里不再做相关的阐述。但有一点需要注意,如果还有一个斜体轴(或者只有一个斜体轴而没有倾斜轴),此时最好完全忽略font-style样式。

@font-face显式指定可变字体的字重轴(wght)、字宽轴(wdth)、斜体轴(ital)和倾斜轴(slnt)是可以起到保护作用的,可以告诉浏览器,如果CSS中使用的值超出了这个范围浏览器应该如何处理。比如,font-weight指定的范围是300~700,但你在使用font-weight时显式的设置了值为100,这个时候浏览器会将font-weight渲染为300,而不会渲染成100。值得注意的是,这个范围只适用于CSS的标准属性,如果你使用font-variation-settings来指定字体权重时(比如 font-variation-settings: "wght" 100),浏览器会认为你是这方面的专家,因此会尝试着合成,即使它超出了正常范围。

Step03:找出可变字体的轴和范围值

每个可变字体的细节都有所不同,在Web上使用可变字体之前,必须要对可变字体所支持的细节有所了解。如果你有可变字体文件,那么可以使用@Roel Nieskens的 WakamaiFondue.com 网站来做检测:

你只需要把本地的字体文件拖到这个网页中,那么 WakamaiFondue.com 就会自动给你生成一份有关于该可变字体相关细节的报告,显示字体的特性、支持的语言、文件大小、字形数量和字体支持的所有可变轴,并显示低/高/默认值。还会生成对应的样式:

您甚至还获得了一个类型测试案例和一些滑动器,以允许您使用不同的轴,并做出相应的调整。

请注意坐标轴、值和缺省值。我们在编写CSS时需要这些信息。如果你本地没有可变字体,而且又想体验一下这方面的感觉,可以点击这里下载测试所需的可变字体

如果你使用的是线上托管的可变字体(比如Google Fonts),想了解对应的相关信息时,可以使用Firefox浏览器来进行了解。比如前面示例中用到的Amstelvar VF字体。在查看页面元素时,选中使用了Amstelvar VF的元素,并选择浏览器“字体”选项卡,就可以看到可变字体的相关信息:

你可以在“字体”面板中调整你想调整的信息,在调整的同时,可以在浏览器中直接看到相应的效果,如果你选择更改选项卡,您可以轻松地复制和粘贴更改后的CSS,将其带回到您的代码中。

.text {
    font-style: italic;
    font-variation-settings: "wght" 501, "wdth" 57.3, "slnt" -9, "ital" 0, "opsz" 23, "MONO" 0, "CASL" 0, "XTRA" 572, "GRAD" -0.47, "XOPQ" 402;
}

整个操作过程如下图所示:

操作是不是很简单,如果你对这个功能感兴趣,还可以观看这方面的视频教程,比如@Jen Simmons录制的Quickly Alter Typography with Firefox Font EditorFirefox Font Editor

Step04:设置可变字体样式

前面的内容已提到多次了,CSS Fonts Module Level 4规范中的font-variation-settings属性可以用来处理可变字体。

  • font-weight:设置可变字体的权重,它的值可以是1~999的任何数字,该属性对应可变字体的wght轴,即font-variation-settings: "wght" 200
  • font-stretch:设置可变字体的字宽(可以对字体进地拉伸或挤压),其值是个百分比值,其中100%对于的是normal关键词,50%对应的是ultra-condensed200%对应的是ultra-expanded。除此之外还有extra-condensedcondensedsemi-condensedsemi-expandedexpandedextra-expanded等关键词。该属性对应的是可变字体中的wdth轴,即font-variation-settings: "wdth" 50,注意,在font-variation-settings中的wdth轴对应的值是不带百分比单位
  • font-style:有两种方式,第一种是大家熟悉的方式,就是将字体设置为斜体,即italic,另一种是倾斜,即oblique,当font-style取值为oblique时,还可以指定字体的倾斜角度,比如oblique 10deg。该属性对应可变字体中的italslnt
  • font-optical-sizing:该属性用来设置字体的光学尺寸,其值有autonone。默认情况下,浏览器会将光学尺寸设置为auto,如果你想将其关闭,可以将其值设置为none。该属性对应的是可变字体中的opsz轴,可以在font-variation-settings中指定opsz,并且其值是一个数字值

比如下面这个小示例:

:root {
    --text-vf-wght: 400;  
    --text-vf-wdth: 95;
    --text-vf-slnt: 9;
    --text-vf-ital: 0;
    --text-vf-opsz: 80;
}

p {
    font-variation-settings:"wght" var(--text-vf-wght), "wdth" var(--text-vf-wdth), "slnt" calc( var(--text-vf-slnt) * -1), "ital" var(--text-vf-ital), "opsz" var(--text-vf-opsz);
}

其对应单个CSS属性:

p {
    font-weight: var(--text-vf-wght); 
    font-stretch: calc(var(--text-vf-wdth) * 1%);
    font-style: oblique calc(var(--text-vf-slnt) * 1deg);
    font-style: italic; 
    font-optical-sizing: auto; 
}

将整个过程所用的代码整合到一起,就会像下面这样:

@font-face {
    font-family: "Amstelvar VF";
    src: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/57225/Amstelvar-Roman-VF_copy.woff2")
        format("woff2 supports variations"), url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/57225/Amstelvar-Roman-VF_copy.woff2")
        format("woff2-variations");
    font-display: swap;
    font-weight: 100 900;
    font-stretch: 75% 125%;
}

:root {
    --text-vf-wght: 400;  
    --text-vf-wdth: 95;
    --text-vf-slnt: 9;
    --text-vf-ital: 0;
    --text-vf-opsz: 80;
}

p {
    font-variation-settings:"wght" var(--text-vf-wght), "wdth" var(--text-vf-wdth), "slnt" calc( var(--text-vf-slnt) * -1), "ital" var(--text-vf-ital), "opsz" var(--text-vf-opsz);
}

上面我们看到的是可变字体中已知的注册轴(实际上并不是所有可变字体都默认有所有注册轴),但有些可变字体根据设计者设计的不同,可能会有N个自定义的注册轴,这些自定义的轴始终以四个大写字母为标记,运用于font-variation-settings属性中

@font-face {
    font-family:'Decovar Regular24'; 
    src:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/209981/Decovar-VF.ttf');
}

p {
    color: #ff8c00;
    font-weight: 800;
    font-style: italic;
    font-variation-settings: "SSTR" 183, "INLN" 648, "TSHR" 460, "TRSB" 312, "TWRM" 638, "SINL" 557, "TOIL" 333, "TINL" 526, "WORM" 523;
}

效果如下:

Step05:降级处理

可变字体是一种较新技术,虽然在2018年中很多主流浏览器都支持该技术,但如果你的业务还需要支持一些更低版本的浏览器时,就难免需要考虑可变字体的降有处理方案。

一般情况下,如果浏览器不支持可变字体的话,将会采用系统级别的字体,但往往这种方式会对整体排版效果有所影响。如果希望在不支持可变字体的浏览器中使用指定的字体,那么我们可以借助条件CSS中的@supports属性来做降级处理。

如果用代码的话,可以像下面这样:

body {
    font-family: 'Venn', sans-serif;
}

@supports (font-variation-settings: normal) {
    body {
        font-family: 'Venn VF', sans-serif;
    }
}

同样的,你要是在做一个响应式Web应用,那么在不同的断点中可以指定不同的注册轴值,这样排版效果会更完善一些:

h1 {
    font-size: 1.8rem;
    line-height: 1.1;
    font-variation-settings: "wdth" 75;
}

p {
    font-size: 1.1rem;
    line-height: 1.5;
    font-variation-settings: "wdth" 88;
}

@media screen and (min-width: 460px) and (max-width: 699px) {
    h1 {
        font-variation-settings: "wdth" 85;
    }
    p {
        line-height: 1.6;
        font-variation-settings: "wdth" 95;
    }
}

Step06:给可变字体添加动画效果

通过CSS的transitionanimation也可以给可变字体添加动画效果。比如,在不同的状态下改变font-variation-settings的值,就可以让可变字体动起来,比如下面这个示例,在鼠标悬浮状态下(:hover)改变font-variation-settings值:

p {
    font-weight: 800;
    font-style: italic;
    font-variation-settings: "SSTR" 183, "INLN" 648, "TSHR" 460, "TRSB" 312, "TWRM" 638, "SINL" 557, "TOIL" 333, "TINL" 526, "WORM" 523;
    transition: font-variation-settings .28s ease;

    &:hover {
        font-weight: 400;
        font-style: normal;
        font-variation-settings: "SSTR" 283, "INLN" 248, "TSHR" 160, "TRSB" 112, "TWRM" 338, "SINL" 257, "TOIL" 133, "TINL" 426, "WORM" 223;
    }
}

除此之外,在@keyframes不同的帧中指定不同的font-variation-settings的值,然后在animation中引入@keyframes中指定的动画,也可以实现可变字体动画效果,比如下面这个示例:

@font-face {
    font-family:'Decovar Regular24'; 
    src:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/209981/Decovar-VF.ttf');
}

h1 {
    margin: 0;
    font-size: 20vw;
    font-family: "Decovar Regular24"; 
    color: white; 
    
    font-variation-settings: 'SSTR' 1000;
    animation: loadin 4s infinite linear;
}

@keyframes loadin {
    0% {
        font-variation-settings: 'SSTR' 1000;
    }
    50% {
        font-variation-settings: 'SSTR' 0;
    }
}

我们可以进一步利用这些概念,将可变字体和JavaScript的一些API结合在一起实现一些不同的交互效果。重要的是,无论你是使用设备的朝向、光线传感器、视窗大小、滚动事件还是鼠标移动,其中基本的JavaScript是不会改变的。

比如下面这个示例,使用鼠标移动来改变可变字体相关的值,因而产生具有弹性的效果:

再来看另外一个示例,将可变字体和JavaScript中的Audio API结合在一起所产生的效果:

有关于这方面更详细的介绍,还可以阅读:

Step07: 性能优化

一般来说,可变字体可以提高性能,因为你只需要使用一个字体文件。静态字体需要在站点上为不同的变体加载不同的字体文件,而可变字体本质上是动态的。换句话说,它们在一个文件中包含了所有的可能,这意味着只有一个HTTP请求,而不是多个。此外,你只需要使用一个@font-face规则,这将生成更小的CSS文件。

另一方面,可变字体文件非常大,因为它包含了所有的变化。例如Roboto可变字体的TTTF格式为3.36MB,而静态的Roboto字体变体的TTF格式文件大约为165~175kb。即使我们需要使用所有的变体(大约有12种变体),总共也只有约2MB

最终,可变字体的性能权衡取决于这两个指标,即HTTP请求的数量和字体文件的总大小。

除此之外,在Web中使用可变字体,我们还可以采用一些性能优化的技术来提高可变字体给Web性能造成的影响。比如使用DNS PrefetchingPreconnect

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

也可以使用CSS的font-display: swap@font-face进行声明,告诉浏览器显示回退字体,直到可变字体可用为止:

@font-face {
    font-family: 'Roboto';
    src: local('Roboto Thin Italic'),
url(https://fonts.gstatic.com/s/roboto/v19/KFOiCnqEu92Fr1Mu51QrEz0dL-vwnYh2eg.woff2)
format('woff2');
    font-display: swap;
}

开发者可以将 <link rel="preload">font-display 配合使用,以很好地控制字体加载与渲染,而不会增加很多开销。 但是,如果您需要进一步自定义,而且愿意承担运行 JavaScript 所引入的开销,还有一个选项可供选择。

Font Loading API 提供一种脚本编程接口来定义和操纵 CSS 字体,追踪其下载进度,以及替换其默认延迟下载行为。 例如,如果您确定需要特定字体变体,您可以对其进行定义并指示浏览器立即提取字体资源:

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
    style: 'normal', unicodeRange:'U+000-5FF', weight:'400'
});

font.load().then(function() {
    document.fonts.add(font);
    document.body.style.fontFamily = "Awesome Font, serif";

    var content = document.getElementById("content");
    content.style.visibility = "visible";
});

另外就是,字体资源通常是不会频繁更新的静态资源。 因此,它们非常适合较长的 max-age 到期,即确保您为所有字体资源同时指定了条件 ETag 标头最佳 Cache-Control 策略

如果您的网页应用使用 Service Worker,则使用缓存优先策略提供字体资源适合于大部分用例。

不应使用 localStorageIndexedDB 来存储字体;这两者自身都有一些性能问题。 浏览器的 HTTP 缓存可以提供最佳且最可靠的机制来向浏览器提供字体资源。

如果你对@font-face引用自定义字体(可变字体)性能优化方面感兴趣的话,还可以阅读:

使用可变字体的陷阱

可变字体对于Web的排版来说更丰富了,但是随着新技术的发展,需要注意的地方也就多了。

  • 可选性太多:可变字体提供了很多以最微小的方式来改变某事的可能性,但这样选择就变得更加困难了。
  • 需要更多的排版知识:可变字体有很多东西可供选择,这意味着你必须清楚自己想要什么,以及为什么想要。它也更易于搞砸,更容易在你的设计中出现不一致。这也涉及到评估什么是合适的字体。当然,你可以像以前一样只使用全名实例,而忽略其他选项。唯一改变的是你只需要加载的一个字体文件。
  • 并不总是有性能上的提高:如果你只需要一种字体样式,那么可变字体文件将会更大。大多数情况下,当你需要三到四种不同的字体权重或字宽时,你将开始节省文件大小。

小结

可变字体是有意义的,而且易于丰富Web排版。也更易于还原设计师期望的效果,另外就是,到目前为止,很多主流浏览器已经支持了可变字体技术,但对于可变字体的使用还是有一定的障碍性,比如文章中提到的性能(可变字体类型,字体文件越大)以及可变字体的设计(并不是人人都能设计出想要的字体)。在这篇文章中,主要和大家探讨了有关于可变字体相关技术以及如何在Web中的使用。最后希望该文能帮助你对可变字体有一定的了解。如果你对这方面技术感兴趣的话,还可以阅读: