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

浏览器支持

  • 77
  • 79
  • 75
  • 15.4

您可以使用 loading 属性来延迟加载图片,而无需编写自定义延迟加载代码或使用单独的 JavaScript 库。以下是该功能的演示

延迟加载的图片会在用户滚动网页时加载。

本页详细介绍了如何在浏览器中实现延迟加载。

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

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

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

这两种方式都可让开发者包含延迟加载行为,并且许多开发者已经构建了第三方库来提供更易于使用的抽象。

不过,由于浏览器直接支持延迟加载,因此无需外部库。浏览器级别的延迟加载还可确保即使客户端停用 JavaScript,图片加载仍可正常进行。但请注意,只有在启用 JavaScript 后,才会延迟加载。

loading 属性

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

您可以使用 loading 属性完全推迟加载屏幕外图片:

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

以下是 loading 属性支持的值:

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

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

eager 值是指示照常加载图片,不会在图片位于屏幕之外时进一步延迟加载。与没有 loading 属性的图片相比,它加载该图片的速度不会比其他图片快。

如果要提高重要图片(例如 LCP 图片)的提取优先级,请结合使用提取优先级fetchpriority="high"

包含 loading="lazy"fetchpriority="high" 的图片在离开屏幕时仍会延迟,然后在几乎位于视口内时以高优先级提取。实际上,这种组合并不是必需的,因为浏览器仍然可能会以高优先级加载该图片。

与视口的距离阈值

所有无需滚动即可看到的图片都将正常加载。只有在用户在其附近滚动时,系统才会提取远低于设备视口的图片。

Chromium 的延迟加载实现旨在确保屏幕外图片提前加载,以便在用户滚动到它们之前完成加载,具体方法是在图片在视口中显示之前进行抓取。

距离阈值因以下因素而异:

您可以在 Chromium 源代码中找到不同有效连接类型的默认值。您可以通过在开发者工具中限制网络来试用这些不同的阈值。

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

2020 年 7 月,Chrome 做出了重大改进,调整了图片延迟加载与视口的距离阈值,以更好地满足开发者的预期。

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

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

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

旧阈值与新阈值:

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

以及新的阈值与 LazySizes(一种热门的 JavaScript 延迟加载库)进行比较:

在相同的网络条件下,Chrome 中与视口之间的距离阈值分别为 90KB 和 70KB。
比较了 Chrome 和 LazySizes 中用于延迟加载的阈值。

提供图片尺寸属性

浏览器加载图片时,不会立即知道图片的尺寸,除非已明确指定。为了让浏览器在网页上预留足够的图片空间,并避免破坏性的布局偏移,我们建议为所有 <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> 代码,但延迟加载可能会使其变得更重要。

Chromium 中的延迟加载功能在图片显示时更有可能立即加载,但仍有可能在适当的时间加载。如果发生这种情况,不为图片指定 widthheight 会增加它们对 Cumulative Layout Shift 的影响。如果您无法指定图片的尺寸,则采用延迟加载方式可以节省网络资源,但会出现这些增加布局偏移的风险。

在大多数情况下,如果您未指定尺寸,图片仍会延迟加载,但也有一些极端情况需要注意。如果未指定 widthheight,图片尺寸默认为 0×0 像素。如果您有一个图库,浏览器可能会在开始时确定所有图片都放入视口内,因为每张图片都不会占用任何空间,并且也不会被推送到屏幕之外。在这种情况下,浏览器决定加载所有内容,这会减慢网页加载速度。

如需查看 loading 如何处理大量图片的示例,请参阅此演示

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

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

虽然浏览器会决定从任意 <source> 元素加载哪张图片,但您只需将 loading 添加到回退 <img> 元素中即可。

始终在第一个视口中显示即时加载图片

对于用户首次加载网页时可见的图片(尤其是 LCP 图片),请使用浏览器默认的即时加载,以便立即可用。如需了解详情,请参阅过多延迟加载的性能影响

请仅对初始视口以外的图片使用 loading=lazy。在知道图片在页面上的位置之前,浏览器无法延迟加载图片,这会导致加载速度变慢。

<!-- 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" 可以阻止在不可见但处于计算距离内的图片加载。这些图片可能位于轮播界面后面,或者针对特定屏幕尺寸被 CSS 隐藏。例如,Chrome、Safari 和 Firefox 不会在图片元素或父元素上使用 display: none; 样式加载图片。但是,其他图片隐藏技术(例如使用 opacity:0 样式)仍然会导致浏览器加载图片。请务必全面测试您的实现,确保其能够按预期运行。

Chrome 121 更改了轮播界面等横向滚动图片的行为。现在,它们使用与垂直滚动相同的阈值。这意味着,对于轮播界面用例,图片会先加载,然后才显示在视口中。这意味着图片加载不太可能被用户注意到,但代价是下载次数更多。使用水平延迟加载演示比较 Chrome 与 Safari 和 Firefox 中的行为。

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

由于新型浏览器内置了对延迟加载的全面支持,您可能不需要使用第三方库或脚本来延迟加载图片。

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

如何处理不支持延迟加载的浏览器?{browsers-dont-support}

请创建一个 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 不受支持,请从 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> 也已经过标准化处理。这样,您就可以使用 loading 属性延迟加载 iframe。如需了解详情,请参阅是时候延迟加载屏幕外 iframe 了!

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

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

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

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

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

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

延迟加载图片以提高性能

浏览器对延迟加载图片的支持可让您大幅更轻松地提升网页性能。

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