Code前端首页关于Code前端联系我们

优化 CSS 性能的一般策略@font-face

terry 2年前 (2023-09-27) 阅读数 81 #数据结构与算法

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 支持的字符可以有以下类型: 字体加载CSS @font-face性能优化的常用策略

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,即使页面元素没有使用合适的字体,也会被下载。

在其他浏览器中也有所不同。

例如,在FirefoxIE 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 就会下载该字体,无论该字体是否实际使用。

  • Firefox、IE 9+ 仅当定义了 font-face 并且该字体应用于页面上的元素时,才会下载该字体,无论该元素的文本内容如何。
  • 仅当定义了 font-face 并且该字体应用于页面上的元素且该元素具有文本内容时,Chrome 和 Safari 才会下载字体。
  • 那你可能会问,如果动态插入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的形式加载的。

    结论

    整体字体加载策略可以用这张图总结如下: 字体加载CSS @font-face性能优化的常用策略

    参考

    本文主要翻译自以下博客文章

    1. https://www.zachleat。 /web/complex-webfonts/#font-display
    2. https://dev.opera.com/articles/better-font-face/

    作者:腾讯IVWEB团队
    来源:掘金

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    热门