针对 Web 的浏览器级图片延迟加载

内置延迟加载功能终于来了!

Web 现在支持延迟加载图片!此视频展示了该功能的演示

您可以使用 loading 属性来延迟加载图片,而无需编写自定义延迟加载代码或使用单独的 JavaScript 库。我们来详细了解一下。

浏览器兼容性

浏览器支持

  • 77
  • 79
  • 75
  • 15.4

不支持 loading 属性的浏览器会直接忽略它,而不会产生副作用。

为什么要采用浏览器级延迟加载?

根据 HTTP Archive 的数据,图片是大多数网站最常被请求的素材资源类型,占用的带宽通常比其他任何资源都要多。在第 90 个百分位,网站在桌面设备和移动设备上发送的图片超过 5 MB。那就是一大堆猫咪图片

以前,您可以通过以下两种方法延迟加载屏幕外图片:

这两种方式都可让开发者加入延迟加载功能,而且许多开发者已经构建了第三方库来提供更易于使用的抽象。不过,由于浏览器直接支持延迟加载,因此无需外部库。浏览器级别的延迟加载还可确保即使客户端上停用了 JavaScript,延迟加载图像仍可正常发挥作用。

loading 属性

Chrome 会以不同的优先级加载图片,具体取决于这些图片相对于设备视口的位置。视口下方的图片会以较低的优先级加载,但仍会在网页加载时抓取。

您可以使用 loading 属性完全推迟加载通过滚动到达的屏幕外图片:

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

以下是 loading 属性支持的值:

  • lazy:延迟加载资源,直到资源与视口达到计算出的距离为止。
  • eager:浏览器的默认加载行为,等同于不添加该属性,并表示无论图片位于网页上的何处,系统都会加载图片。虽然这是默认设置,但如果您的工具在没有明确值时自动添加 loading="lazy",或者如果 linter 提示未明确设置,则显式设置会很有用。

loading 属性与提取优先级之间的关系

eager 值只是一个指令,用于照常加载图片,而不会在图片在屏幕之外时进一步延迟加载。这并不意味着该图片的加载速度比没有 loading="eager" 属性的其他图片快。

浏览器会根据各种启发法来确定资源的优先级,而 loading 属性只是说明图片资源何时加入队列,而不是说明它在该队列中的优先级。eager 只是表示浏览器默认使用的即时队列。

如果您想提高重要图片(例如 LCP 图片)的提取优先级,则应将提取优先级fetchpriority="high" 搭配使用。

请注意,包含 loading="lazy"fetchpriority="high" 的图片在离开屏幕时仍会延迟,然后在几乎位于视口内时以高优先级抓取。在这种情况下,系统仍然可能会以高优先级抓取相应网址,因此实际上不应需要使用也不会使用此组合。

与视口的距离阈值

所有位于首屏的图片(即无需滚动即可看到的图片)可正常加载。只有在用户靠近设备视口时,系统才会提取远低于设备视口的图片。

Chromium 的延迟加载实现旨在确保屏幕外图片尽早加载,以便在用户滚动到它们附近时完成加载。通过在附近的图像显示在视口中之前对其进行抓取,我们可以最大限度提高这些图像在显示时已加载完毕的可能性。

与 JavaScript 延迟加载库相比,用于提取滚动进入视图的图片的阈值可能比较保守。

距离阈值并非固定不变,而是取决于多种因素:

您可以在 Chromium 源代码中找到不同有效连接类型的默认值。随着 Chrome 团队改进启发法来确定何时开始加载,这些数字,甚至是仅在距离视口达到一定距离时才进行提取的方法可能会发生变化。

改进了数据节省设置和与视口的距离阈值

自 2020 年 7 月起,Chrome 进行了重大改进,使图片延迟加载与视口之间的距离阈值保持一致,以更好地满足开发者的预期。

对于快速连接 (4G),我们已将 Chrome 与视口的距离阈值从 3000px 减少到 1250px;在连接速度较慢(3G 或更低连接)时,我们将阈值从 4000px 更改为了 2500px。这一变更有两个目的:

  • <img loading=lazy> 的行为更接近 JavaScript 延迟加载库提供的体验。
  • 新的视口与视口的距离阈值仍然能够让我们保证,在用户滚动到图片之前,图片可能已加载完毕。

以下是我们的某个快速连接 (4G) 演示示例,在新旧距离阈值之间进行了比较:

旧阈值与新阈值:

针对图片延迟加载推出经过改进的新阈值,将快速连接的与视口的距离阈值从 3000 像素降低至 1250 像素

以及 LazySizes(一种热门的 JS 延迟加载库)的新阈值:

在相同的网络条件下,Chrome 中与视口之间的距离阈值分别为 90KB 和 70KB。

我们致力于与网络标准社区合作,探索在不同浏览器之间实现与视口的距离阈值的方式更加一致。

图片应包含尺寸属性

浏览器加载图片时,并不会立即知道图片的尺寸(除非已明确指定)。为使浏览器在网页上为图片预留足够的空间,建议所有 <img> 标记都同时包含 widthheight 属性。如果不指定尺寸,就会发生布局偏移,这种变化在需要一些时间才能加载的网页中更加明显。

<img src="image.png" loading="lazy" alt="…" width="200" height="200">

或者,也可以直接在内嵌样式中指定它们的值:

<img src="image.png" loading="lazy" alt="…" style="height:200px; width:200px;">

设置尺寸的最佳做法适用于 <img> 代码,无论它们是否被延迟加载。通过延迟加载,您可以提高相关性。为现代浏览器中的图片设置 widthheight 还允许浏览器推断其固有大小。

在大多数情况下,如果未添加尺寸,图片仍会延迟加载,但也有一些极端情况需要注意。如果未指定 widthheight,最初的图片尺寸为 0×0 像素。如果您有一个此类图片的图库,浏览器可能会在开始时断定所有图片都适合视口,因为每张图片几乎不占用任何空间,并且没有图片被推到屏幕之外。在这种情况下,浏览器确定所有这些对象对用户可见,并决定加载所有内容。

此外,指定图片尺寸可降低发生布局偏移的可能性。如果您无法为图片添加尺寸,则可以采用延迟加载方式,在节省网络资源和增加布局偏移风险之间进行权衡。

虽然 Chromium 中的延迟加载是这样实现的:图片在可见后可能会加载,但仍然有可能尚未加载这些图片。在这种情况下,此类图片上缺少 widthheight 属性会增加其对 Cumulative Layout Shift 的影响。

使用 <picture> 元素定义的图片也可以延迟加载:

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">
  <img src="photo.jpg" loading="lazy">
</picture>

虽然浏览器会决定从任意 <source> 元素加载哪张图片,但 loading 属性只需要添加到后备 <img> 元素中。

避免延迟加载位于第一个可见视口中的图片

您应避免为位于第一个可见视口中的任何图片设置 loading=lazy。这与 LCP 图片密切相关。如需了解详情,请参阅过多延迟加载对性能的影响一文。

建议尽可能仅向位于非首屏的图片添加 loading=lazy。可以立即提取紧急加载的图片,而延迟加载的图片目前需要等待,直到知道图片在网页上的位置,这依赖于 IntersectionObserver 可用。

一般而言,视口中的任何图片都应使用浏览器的默认设置快速加载。如果是视口内图片,则无需指定 loading=eager,即可出现这种情况。

<!-- visible in the viewport -->
<img src="product-1.jpg" alt="..." width="200" height="200">
<img src="product-2.jpg" alt="..." width="200" height="200">
<img src="product-3.jpg" alt="..." width="200" height="200">

<!-- offscreen images -->
<img src="product-4.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-5.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-6.jpg" loading="lazy" alt="..." width="200" height="200">

优雅降级

不支持 loading 属性的浏览器将忽略该属性。虽然这些浏览器当然无法享受延迟加载带来的好处,但添加 属性不会对它们产生负面影响。

常见问题解答

是否有计划在 Chrome 中自动延迟加载图片?

以前,如果在 Chrome(Android 版)启用了精简模式且未提供 loading 属性或将其设为 loading="auto",则 Chromium 会自动延迟加载适合延迟的所有图片。不过,精简模式已废弃(与非标准 loading="auto" 一样),且目前还没有计划在 Chrome 中提供自动延迟加载图片的功能。

能否更改在触发加载操作之前图片需要的距离?

这些值是硬编码的,不能通过 API 更改。不过,随着浏览器尝试不同的阈值距离和变量,它们将来可能会发生变化。

CSS 背景图片可以使用 loading 属性吗?

不可以,它目前只能与 <img> 标记一起使用。

延迟加载设备视口内的图片是否有缺点?

避免在首屏图片上放置 loading=lazy 会更安全,因为 Chrome 不会在预加载扫描程序中预加载 loading=lazy 图片,并且还会延迟获取此类图片,直到所有布局完成为止。如需了解详情,请参阅避免延迟加载位于第一个可见视口中的图片

使用 loading="lazy" 可能会阻止在不可见且在计算距离内加载它们。例如,Chrome、Safari 和 Firefox 不会使用 display: none; 样式加载图片,无论是在图片元素上还是在父元素上。不过,其他隐藏图片的方法(例如使用 opacity:0 样式设置)仍会加载图片。请务必全面测试您的实现,确保其能够按预期运行。

如果我已经在使用第三方库或脚本来延迟加载图片,该怎么办?

鉴于新型浏览器现已全面支持原生延迟加载,您可能需要重新考虑是否仍需使用第三方库或脚本来延迟加载图片。

继续使用第三方库与 loading="lazy" 的一个原因是,为不支持该属性的浏览器提供 polyfill,或者更好地控制何时触发延迟加载。

如何处理不支持延迟加载的浏览器?

请创建一个 polyfill 或使用第三方库在您的网站上延迟加载图片。loading 属性可用于检测浏览器是否支持该功能:

if ('loading' in HTMLImageElement.prototype) {
  // supported in browser
} else {
  // fetch polyfill/third-party library
}

例如,lazysizes 就是一种常用的 JavaScript 延迟加载库。您可以检测对 loading 属性的支持,以便在 loading 不受支持时将延迟大小作为后备库加载。工作原理如下:

  • <img src> 替换为 <img data-src>,以避免在不受支持的浏览器中急于加载。如果 loading 属性受支持,请将 data-src 替换为 src
  • 如果 loading 不受支持,则加载回退 (lazysizes) 并启动它。根据 Lazysize 文档,您可以使用 lazyload 类来指明延迟加载哪些图片。
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt="…">

<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="cats.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="dogs.jpg" alt="…" loading="lazy" class="lazyload">

<script>
  if ('loading' in HTMLImageElement.prototype) {
    const images = document.querySelectorAll('img[loading="lazy"]');
    images.forEach(img => {
      img.src = img.dataset.src;
    });
  } else {
    // Dynamically import the LazySizes library
    const script = document.createElement('script');
    script.src =
      'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js';
    document.body.appendChild(script);
  }
</script>

此处提供了此模式的演示。请在旧版浏览器中试用此功能,看看后备广告的实际效果。

浏览器是否也支持 iframe 延迟加载?

浏览器支持

  • 77
  • 79
  • 121
  • 16.4

<iframe loading=lazy> 也已标准化,在 Chromium 和 Safari 中也已实现。这样,您就可以使用 loading 属性延迟加载 iframe。有关详情,请参阅这篇有关 iframe 延迟加载的专门文章

浏览器级延迟加载对网页上的广告有何影响?

与任何其他图片或 iframe 一样,系统会以图片或 iframe 延迟加载的形式向用户展示所有广告。

系统在打印网页时如何处理图片?

打印网页时所有图片和 iframe 会立即加载。请参阅问题 875403 了解详情。

Lighthouse 是否可以识别浏览器级延迟加载?

Lighthouse 6.0 及更高版本将屏幕外图片延迟加载方法考虑在内,这些方法可能使用不同的阈值,使其能够通过推迟屏幕外图片审核。

总结

通过支持延迟加载图片,您可以显著提高网页性能。

您是否注意到在 Chrome 中启用此功能后出现任何异常行为?提交错误