字体与图片优化:font-display、picture 与 AVIF/WebP
发布于 更新于
一句话: font-display CSS 描述符控制在网络字体加载期间文本是保持不可见还是以
回退字体渲染,而 <img> 元素的 loading 属性控制何时获取图片、fetchpriority
提示其相对优先级,AVIF、WebP 等格式则改变这次获取需要传输多少数据。
用 font-display 控制字体加载期间的可见性
Section titled “用 font-display 控制字体加载期间的可见性”根据 MDN,font-display 为 @font-face 规则定义了一个阻塞期(浏览器为等待字体而
隐藏文本的时长)和一个交换期(字体到达后仍会被换入的时长)。swap 值给出极短的
阻塞期,因此文本几乎立即以回退字体渲染,网络字体到达后再换入:
@font-face { font-family: "Brand Sans"; src: url("/fonts/brand-sans.woff2") format("woff2"); font-weight: 400; font-display: swap;}根据 MDN,font-display 属于 Baseline 广泛可用,自 2020 年 1 月起获得支持。
延迟加载与设置图片优先级
Section titled “延迟加载与设置图片优先级”根据 MDN,<img> 元素的 loading 属性中,lazy 会将加载推迟到图片被计算为接近
视口时,而默认值 eager 会立即加载;这种延迟仅在启用 JavaScript 时才生效——当脚本
被禁用时,loading="lazy" 不会产生任何效果。fetchpriority 属性则单独提示该次获取的
相对优先级:
<img src="/images/hero.avif" width="1200" height="630" loading="eager" fetchpriority="high" alt="Product hero shot"/><img src="/images/gallery-3.avif" width="400" height="300" loading="lazy" alt="Gallery photo 3"/>根据 MDN,每张图片都建议显式设置 width 与 height,对 loading="lazy" 的图片尤其
如此:没有这两个属性的图片在加载完成前布局尺寸为 0×0,而根据 MDN,一张浏览器认为
没有尺寸的未加载图片,如果它从未与某个可见元素的区域相交,就可能永远不会加载。
根据 MDN,font-display 属于 Baseline 广泛可用。对于图片,<img> 的 loading 与
fetchpriority 在当前浏览器中已被广泛支持。AVIF 在 Chrome、Edge 与 Opera 中受支持,
Firefox 从 Firefox 93 起、Safari 从 Safari 16.1 起为其添加了支持——支持历史比 WebP 更短;
根据 MDN,WebP 在 Chrome、Edge、Firefox、Opera 与 Safari 的当前版本中均受支持,因此格式
回退链对 AVIF 而言仍然重要,尤其是面向使用较旧浏览器版本的用户时。
用 AVIF 和 WebP 搭配 JPEG 回退提供图片
Section titled “用 AVIF 和 WebP 搭配 JPEG 回退提供图片”根据 MDN,AVIF 在质量相近的情况下通常比 JPEG 小约 50%,WebP 的有损模式通常比 JPEG
小 25%-35%。<picture> 包裹一个或多个 <source> 元素,并搭配一个回退用的 <img>:
<picture> <source srcset="/images/hero.avif" type="image/avif" /> <source srcset="/images/hero.webp" type="image/webp" /> <img src="/images/hero.jpg" width="1200" height="630" alt="Product hero shot" /></picture>特性检测与回退
Section titled “特性检测与回退”根据 MDN,HTMLImageElement.decode() 返回一个 Promise,图片准备好可用时会 resolve,
解码失败时则会以 EncodingError reject。出现这种情况可能是因为图片请求失败、调用
decode() 后请求发生变化,或图片数据已损坏。代码可以在这次尝试被 reject 时选择回退,
但仅凭这次 reject 不能确定浏览器缺少 AVIF 解码支持:
let avifSupportPromise;function canDecodeAvifProbe() { if (avifSupportPromise) return avifSupportPromise; if (!('Image' in window)) { avifSupportPromise = Promise.resolve(false); // 没有 Image 构造函数:跳过探测。 return avifSupportPromise; } const probe = new Image(); probe.src = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEDQgMgkxIABJSElBQkJB'; avifSupportPromise = probe .decode() .then(() => true) .catch(() => false); // 本次尝试失败:选择回退图片。 return avifSupportPromise;}- 根据 MDN,通过
<picture>或其他方式为 AVIF 提供 WebP、JPEG 或 PNG 回退—— AVIF 需要完整下载后才能渲染任何内容,且它在当前浏览器中的支持历史比 WebP 更短。 - 为每张图片设置
width与height,尤其是loading="lazy"的图片,这样浏览器 才有已知的布局尺寸,图片才能被找到并加载。 - 根据 MDN,
fetchpriority只是向浏览器提示相对优先级,而非保证——因此把high留给最重要的那些图片。 - 根据 MDN,
font-display的默认值(auto)由浏览器自行决定阻塞行为;如果想要swap或optional所定义的那种极短阻塞期,需要显式设置。 - 参见资源提示了解
rel="preload"。