优化 CSS 性能的一般策略@font-face
1。 font-face 的基本使用
font-face 的基本使用大家都应该知道,基本就是这样:
@font-face {
font-family: Lato;
src: url('font-lato/lato-regular-webfont.woff2') format('woff2'),
url('font-lato/lato-regular-webfont.woff') format('woff'),
url(font-lato/lato-regular-webfont.ttf) format("opentype");
}
p { font-family: Lato, serif; }
复制代码 就这样吧,我们的网页上使用一种特殊的字体吧。除了font-family和src属性外,它还有font-style和font-weight属性。 src 可以指定多种字体,这些字体将按顺序应用。例如,在上面的示例中,将首先加载 woff2 字体。如果失败,将加载 woff 字体。否则,将加载 opentype 字体。 src 支持的字符可以有以下类型:
src 参数可以带或不带引号。不同的参数格式有不同的含义,例如:
src: url(fonts/simple.woff); /* 加载simple.woff,地址相对于样式表的地址 */
src: url(/fonts/simple.woff); /* 加载simple.woff,地址是网站的绝对地址 */
src: url(fonts/coll.otc#foo); /* 从coll.otc字符集中加载foo字体 */
src: url(fonts/coll.woff2#foo); /* 从coll.woff2字符集中加载foo字体 */
src: url(fonts.svg#simple); /* 加载id 为'simple'的SVG字体 */
复制代码src 中加载的字体地址受到跨域限制。如果您想在您的域上运行字体,则需要设置 CORS。
这是font-face最基本的用法。接下来,我们将进一步分析font-faces的使用情况,找出尽可能多的优化策略。
2。字体什么时候下载?
上面已经介绍了字体的基础知识,但是你有没有想过在下载字体的时候呢?当我们在CSS中定义以下样式时,页面加载时会自动下载字体吗?
@font-face {
font-family: Lato;
src: url('font-lato/lato-regular-webfont.woff2') format('woff2'),
url('font-lato/lato-regular-webfont.woff') format('woff'),
url(font-lato/lato-regular-webfont.ttf) format("opentype");
}
复制代码不幸的是,该字体无法下载。 一般情况下,只有当我们的页面元素使用了font-face中定义的字体时,才会下载对应的字体。
注:我们这里讨论的是正常情况。这是因为只要在IE8中定义了font-face,即使页面元素没有使用合适的字体,也会被下载。
在其他浏览器中也有所不同。
例如,在Firefox和IE 9+中,在以下情况下也会下载字体:❀s html css
#test {
font-family: Lato;
}
复制代码?您可能已经注意到,虽然该元素使用 font-family: Lato 样式,但该元素没有任何文本! ! ! 。根据我们的理想情况,只有当有文本内容时才应该下载字体。这就是 Chrome、Safari(WebKit/Blink 等)浏览器的行为。浏览器
Chrome、Safari(WebKit/Blink等)只会在以下相同情况下下载字体:
html
<div id="test">这里是有文本的哦</div>
复制代码css
#test {
font-family: Lato;
}
复制代码所以总结一下,♼针对不同浏览器的下载策略:IE8只要定义了 font-face 就会下载该字体,无论该字体是否实际使用。
那你可能会问,如果动态插入DOM元素怎么办?例如:
var el = document.createElement('div');
el.style.fontFamily = 'open_sansregular';
document.body.appendChild(el);
el.innerHTML = 'Content.';
复制代码答案是一样的,下载策略如下:
var el = document.createElement('div');
el.style.fontFamily = 'open_sansregular';
/* 到这里,IE8就会开始下载字体 */
document.body.appendChild(el);
/* 只有到这里,Firefox, IE 9+ 才会开始下载字体 */
el.innerHTML = 'Content.';
/* 只有到这里,Chrome, Safari 才会开始下载字体 */
复制代码3. FOIT (Flash of Invisible Text)
FOIT是浏览器加载字体时的默认表示,即,当字体加载过程中,无法查看页面的文字内容。在现代浏览器中,FOIT 将导致此行为长达 3 秒。 FOIT 会导致糟糕的用户体验,这是应该避免的。
4。 FOUT(Flash of Unstyled Text)和字体显示属性
FOUT表示在字体加载过程中使用默认的系统字体。字体加载完成后,会显示加载的字体。如果超过 FOIT(3s) 如果字体还没有加载,则继续使用默认的系统字体。
IE浏览器和Edge不会等待FOIT超时才显示默认字体,而是立即显示默认字体。 FOUT 比 FOIT 更好,但必须考虑它引起的回流。
那么为了让浏览器有FOUT行为,我们需要在设置@font-face的时候添加一个属性:font-display。默认字体显示为auto,可选属性及含义如下:
- auto。字体显示策略由用户代理确定。
- 块。为字体提供较短的阻塞时间(大多数情况下建议 3 秒)和无限的交换时间。
- 交换。为字体提供非常小的块周期(在大多数情况下建议 100 毫秒或更短)和无限的交换时间。
- 后备。时间(大多数情况下建议 100 毫秒或更短)和短交换时间(大多数情况下建议 3 秒)。
- 可选。给脸部字体一个非常小的阻塞时间(大多数情况下建议100ms或更短)和0s的交换时间。
通常设置为后备和可选。
5。预加载
将以下代码添加到页面中以更快地加载字体:
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
复制代码通常与最基本的字体用法结合使用
6。将字体转换为 BASE64URI
在 @font-face 中指定字体时的路径会立即更改为 base64 字体编码。
优点:这种方式的优点是不会生成FOIT和FOUT。所以不会有回流焊和重绘。缺点:转换成base64的字体也会太大,影响首页的加载速度。不支持以逗号分隔格式上传多种格式的字体,只能加载一种字体格式。这就导致了,为了尽可能保证所有浏览器兼容,通常会指定woff格式,因为woff格式兼容性好,但不能使用小woff2格式,因为woff2格式兼容性差。
7。异步加载 BASE64 格式的 URI 字体
此方法用于异步插入具有 BASE64 格式的 URI 字体的 CSS 链接。
8. 使用 Font Load API + FOUT + 类切换
该方法首先不使用使用 @font-face 的类,然后使用 Font Load API 加载要使用的字体,然后根据 Just CSS 进行切换。 Font Load API 是原始 API:
document.fonts.load('1em open_sansregular')
.then(function() {
var docEl = document.documentElement;
docEl.className += ' open-sans-loaded';
});
.open-sans-loaded h1 {
font-family: open_sansregular;
}
复制代码当然,这种方法要考虑浏览器兼容性问题。
9。 FOFT (Flash of Faux Text)
FOFT 会将字体加载分成多个部分。它将首先加载罗马网络字体,然后当它包含实际的粗体和斜体时立即使用字体合成属性。渲染粗体和斜体变体。
此方法基于[使用字体加载API + FOUT + 类切换]。非常适合包含相同字体但不同粗细和字体样式,如罗马、粗体、斜体、粗体斜体等。我们将字体分为两个阶段:第一阶段是罗马字体,然后我们立即创建人造粗体字母。和斜体,最后(第二阶段)用真实字体替换它。您还可以使用 sessionStorage 来优化对重复视图的访问。
10。 CRITICAL FOFT
CRITICAL FOFT 和标准 FOFI 之间的唯一区别是在第一阶段包含罗马字体。 CRITICAL FOFT不会打开全套罗马字体,而只打开其中的一个子集(例如A -Za-z0-9),全套在第二阶段加载。
11。 FOFT CRITICAL WITH DATA URI
唯一的区别在于此 FOFT CRITICAL 与罗马子集字体加载方法之间。上一步是使用字体加载 API 完成的。此处,罗马子集字体将被编码为 BASE64 URI。表单已加载。
12。 CRITICAL FOFT WITH PRRELOAD
与上面唯一的区别是第一阶段加载罗马子集字体的方法,是以preload的形式加载的。
结论
整体字体加载策略可以用这张图总结如下:
参考
本文主要翻译自以下博客文章
- https://www.zachleat。 /web/complex-webfonts/#font-display
- https://dev.opera.com/articles/better-font-face/
作者:腾讯IVWEB团队
来源:掘金
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网