改进的字体加载

网页字体在网络上越来越受欢迎。使用网页字体允许网站作者在其网站资产中包含和使用特定字体。浏览器会随着网站的其余部分下载字体,并在下载完成后使用它们。不幸的是,并非所有网页字体都能即时下载,这意味着在加载过程中,浏览器必须在没有字体的情况下显示网页。许多网页字体相当大,导致浏览器在使用它们之前出现长时间延迟。WebKit 在两个主要方面缓解了这个问题:改进字体下载策略,以及加快字体下载速度。

默认字体加载策略

即使由于正在进行下载而无法使用字体,浏览器也应尝试以最佳方式显示网页。WebKit 始终会在字体可用时使用下载的字体;但是,某些字体可能需要相当长的时间才能完成下载。对于这些字体,WebKit 会在延迟期间显示带有不可见文本的元素。旧版本的 WebKit 会继续显示这种不可见文本,直到字体下载完成。相反,新版本的 WebKit 会显示这种不可见文本最多 3 秒,之后它会切换到从元素样式中选择的本地字体,然后在下载完成时最终切换到下载的字体。

这项新策略最大限度地减少了快速下载字体时回退文本的闪烁,同时不会使长时间下载的字体无限期地无法阅读。最棒的是,网站无需做任何事情即可采用这项新策略;所有字体加载都将默认使用它。

CSS 字体加载 API

不同的网页作者可能希望对标题字体或正文字体采用不同的策略。借助 WebKit 中新增的 CSS 字体加载 API,网页作者可以完全控制自己的字体加载策略。

此 API 向 JavaScript 暴露了两个主要部分:FontFace 接口和 FontFaceSet 接口。FontFace 表示与 CSS @font-face 规则相同的概念,因此它包含有关字体的信息,如其 URL、粗细、Unicode 范围、字体族等。文档的 FontFaceSet 包含网页可用于渲染的所有字体。每个文档都有自己的 FontFaceSet,可通过 document.fonts 访问。

使用这些对象实现特定字体加载策略非常简单。一旦构造了 FontFaceload() 方法就会启动字体数据的异步下载。它返回一个 Promise,该 Promise 在下载成功时 fulfilled,在下载失败时 rejected。通过将处理程序链式地添加到返回的 Promise,JavaScript 可以在下载完成时采取行动。因此,网站可以通过使用以下代码来实现立即使用回退字体且没有超时限制的策略:

<div id="target" style="font-family: MyFallbackFont;">hamburgefonstiv</div>
let fontFace = new FontFace("MyWebFont", "url('MyWebFont.woff2') format('woff2'),
    url('MyWebFont.woff') format('woff')");
fontFace.load().then(function(loadedFontFace) {
    document.fonts.add(loadedFontFace);
    document.getElementById("target").style.fontFamily = "MyWebFont";
});

在此示例中,元素被声明式地设置为使用 MyFallbackFont 样式。然后,JavaScript 运行并开始请求 MyWebFont。如果字体下载成功,新下载的字体将添加到文档的 FontFaceSet 中,并且元素的样式将被修改以使用此新字体。

WOFF 2

无论使用何种字体加载策略,当字体下载速度快时,用户体验都会达到最佳。macOS Sierra、iOS 10 和 GTK 上的 WebKit 支持一种名为“WOFF 2”的新型、更小的字体文件格式。字体之所以更小,是因为它们使用了先进的 Brotli 压缩,这意味着 WOFF 2 字体的下载速度可以比使用 WOFF、OpenType 和 TrueType 等其他常见格式表示的相同字体快得多。WebKit 还识别 CSS @font-face 规则内 src 属性中的 format("woff2") 标识符。由于并非所有浏览器都支持 WOFF 2,因此如果浏览器不支持 WOFF 2,可以优雅地回退到其他格式,例如:

@font-face {
    font-family: MyWebFont;
    src: url("MyWebFont.woff2") format("woff2"),
         url("MyWebFont.woff") format("woff");
}

在此示例中,浏览器将使用 format CSS 函数来选择性地下载它们支持的任何字体。由于浏览器会优先选择列表中靠前的字体而不是靠后的字体,因此遇到此代码的浏览器如果支持 WOFF 2 字体,将始终优先选择 WOFF 2 字体而不是 WOFF 字体。

unicode-range

带宽是昂贵的(尤其是对移动设备而言),因此最小化或消除字体下载非常有价值。WebKit 现在将为了字体下载的目的而遵守 unicode-range CSS 属性。考虑以下内容

@font-face {
    font-family: MyWebFont;
    src: url("MyWebFont-extended.woff2") format("woff2"),
         url("MyWebFont-extended.woff") format("woff");
    unicode-range: U+110-24F;
}

@font-face {
    font-family: MyWebFont;
    src: url("MyWebFont.woff2") format("woff2"),
         url("MyWebFont.woff") format("woff");
    unicode-range: U+0-FF;
}
<div style="font-family: MyWebFont;">hamburgefonstiv</div>

在此内容中,所有用 MyWebFont 样式化的字符都不在第一个 CSS @font-face 规则的 unicode-range 范围内,这意味着根本没有理由下载它!然而,重要的是要记住,用网页字体样式化任何字符都会导致最后一个匹配的 @font-face 被下载,以便根据字体的度量正确设置包含元素的大小。因此,最常见的 CSS @font-face 规则应列在最后。使用 unicode-range 来划分字体可以完全消除字体下载,从而节省用户的带宽和电池。

当使用网页字体时,运用这些技术可以显著改善用户在您网站上的体验。欲了解更多信息,请通过 @Litherum 联系我,或通过 @jonathandavisweb-evangelist@apple.com 联系苹果公司网页技术推广大使 Jonathan Davis。