浏览器支持
您可以使用 loading
属性延迟加载图片,而无需编写自定义延迟加载代码或使用单独的 JavaScript 库。以下是该功能的演示:
本页将详细介绍如何在浏览器中实现延迟加载。
为什么要进行浏览器级延迟加载?
根据 HTTP Archive,图像是大多数网站最常请求的素材资源类型,通常比任何其他资源占用更多的带宽。在第 90 个百分位数,网站在桌面设备和移动设备上发送的图片大小超过 5 MB。
以前,您可以通过以下两种方式延迟屏幕外图片的加载:
- 使用 Intersection Observer API
- 使用
scroll
、resize
或orientationchange
事件处理程序
无论是哪种方式,开发者都可以添加延迟加载行为,而且许多开发者都构建了第三方库,以提供更易于使用的抽象。
不过,由于浏览器直接支持延迟加载,因此无需外部库。浏览器级延迟加载还可确保即使客户端停用了 JavaScript,图像加载功能仍可正常运行。不过请注意,只有在启用 JavaScript 后,系统才会延迟加载。
loading
属性
Chrome 会根据图片相对于设备视口的位置,以不同的优先级加载图片。视口下方的图片的加载优先级较低,但仍会在网页加载时提取。
您可以使用 loading
属性完全推迟屏幕外图片的加载:
<img src="image.png" loading="lazy" alt="…" width="200" height="200">
以下是 loading
属性支持的值:
lazy
:延迟加载资源,直到其到达与视口的计算距离。eager
:浏览器的默认加载行为,与不添加该属性的行为相同,表示无论图片位于网页上的什么位置,都会加载该图片。这是默认设置,但如果您的工具在没有明确值时自动添加loading="lazy"
,或者如果您的 lint 检查器在未明确设置时发出警告,则明确设置此值会很有用。
loading
属性与提取优先级之间的关系
eager
值是一个指令,用于照常加载图片,如果图片不在屏幕上,则不会进一步延迟加载。它不会比没有 loading
属性的其他图片更快地加载图片。
如果您想提高重要图片(例如 LCP 图片)的提取优先级,请将提取优先级与 fetchpriority="high"
搭配使用。
具有 loading="lazy"
和 fetchpriority="high"
的图片在屏幕外时仍会延迟,当它几乎位于视口内时,系统会以高优先级提取该图片。这种组合实际上并不必要,因为浏览器无论如何都可能会以高优先级加载该图片。
与视口的距离阈值
所有无需滚动即可立即查看的图片都会正常加载。只有当用户滚动到设备视口下方很远的图片附近时,系统才会提取这些图片。
Chromium 的延迟加载实现会尝试确保尽早加载屏幕外图片,以便在用户滚动到这些图片时,图片已完成加载。为此,系统会在图片在视口中可见之前提前提取它们。
距离阈值因以下因素而异:
- 要提取的图片资源的类型
- 有效的连接类型
您可以在 Chromium 源代码中找到不同有效连接类型的默认值。您可以在 DevTools 中节流网络,以便尝试这些不同的阈值。
改进了数据节省和距离视口阈值
2020 年 7 月,Chrome 进行了重大改进,以使图片延迟加载与视口距离阈值保持一致,从而更好地满足开发者的预期。
在快速连接(4G)中,我们将 Chrome 的视口距离阈值从 3000px
降低到了 1250px
;在较慢的连接(3G 或更低)中,将阈值从 4000px
更改为了 2500px
。这项变更有两个目的:
<img loading=lazy>
的行为更接近 JavaScript 延迟加载库提供的体验。- 新的视口距离阈值仍然意味着,在用户滚动到图片时,图片可能已经加载完毕。
下方显示了在快速连接(4G)下,我们某个演示的旧版与新版视口距离阈值之间的对比情况:
新阈值与 LazySizes(一个常用的 JavaScript 延迟加载库)的对比情况如下:
为图片添加尺寸属性
浏览器在加载图片时,除非明确指定图片的尺寸,否则不会立即知道图片的尺寸。为了让浏览器在网页上为图片预留足够的空间,并避免出现干扰性的布局偏移,我们建议为所有 <img>
标记添加 width
和 height
属性。
<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 中的延迟加载的实现方式使得图片更有可能在可见时立即加载,但仍有可能不会在正确的时间加载。如果发生这种情况,不为图片指定 width
和 height
会增加它们对累计布局偏移的影响。如果您无法指定图片的尺寸,则延迟加载图片可以节省网络资源,但可能会增加布局偏移。
在大多数情况下,即使您未指定尺寸,图片仍会延迟加载,但您应注意一些极端情况。如果未指定 width
和 height
,图片尺寸默认为 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 for Android 上启用了精简模式,并且未提供 loading
属性或将其设置为 loading="auto"
,Chromium 会自动延迟加载非常适合延迟加载的所有图片。不过,精简模式和 loading="auto"
已废弃,我们也无意在 Chrome 中提供自动延迟加载图片的功能。
我可以更改图片在视口中显示之前需要距离视口多近吗?
这些值是硬编码的,无法通过 API 进行更改。不过,随着浏览器尝试使用不同的阈值距离和变量,这些值未来可能会发生变化。
CSS 背景图片可以使用 loading
属性吗?
不可以,您只能将其与 <img>
代码搭配使用。
loading
能否处理视口中未立即显示的图片?
使用 loading="lazy"
可以防止在图片不可见但位于计算的距离内时加载图片。在某些屏幕尺寸下,这些图片可能会位于轮播界面后面或被 CSS 隐藏。例如,Chrome、Safari 和 Firefox 不会在图像元素或父元素上使用 display: none;
样式加载图片。不过,其他图片隐藏技术(例如使用 opacity:0
样式)仍会导致浏览器加载图片。请务必全面测试您的实现,确保其能按预期运行。
Chrome 121 更改了轮播界面等水平滚动图片的行为。这些事件现在使用与垂直滚动相同的阈值。这意味着,对于轮播界面用例,图片会在视口中显示之前加载。这意味着,用户不太可能注意到图片加载,但代价是需要进行更多下载。使用横向延迟加载演示比较 Chrome 与 Safari 和 Firefox 中的行为。
如果我已经在使用第三方库或脚本来延迟加载图片,该怎么办?
由于现代浏览器内置了对延迟加载的全面支持,因此您可能不需要第三方库或脚本来延迟加载图片。
继续将第三方库与 loading="lazy"
搭配使用的一个原因是为不支持该属性的浏览器提供 polyfill,或者更好地控制延迟加载的触发时间。
如何处理不支持延迟加载的浏览器?
所有主要浏览器都支持浏览器级图片延迟加载,对于大多数用例,建议使用此功能,以免对 JavaScript 产生额外的依赖。
不过,如果您需要支持更多浏览器,或者想要更好地控制延迟加载阈值,则可以使用第三方库在您的网站上延迟加载图片。
您可以使用 loading
属性检测浏览器是否支持该功能:
if ('loading' in HTMLImageElement.prototype) {
// supported in browser
} else {
// fetch polyfill/third-party library
}
例如,lazysizes 是一个热门的 JavaScript 延迟加载库。只有在 loading
不受支持时,您才能检测对 loading
属性的支持,以便将 lazysizes 加载为后备库。具体运作方式如下:
- 将
<img src>
替换为<img data-src>
,以避免在不受支持的浏览器中提前加载。如果支持loading
属性,请将data-src
替换为src
。 - 如果不支持
loading
,请从 lazysizes 加载回退项并启动它,使用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 的延迟加载?
浏览器支持
<iframe loading=lazy>
也已标准化。这样,您就可以使用 loading
属性延迟加载 iframe。如需了解详情,请参阅该是延迟加载屏幕外 iframe 的时候了!
浏览器级延迟加载对网页上的广告有何影响?
所有以图片或 iframe 的形式向用户展示的广告都会延迟加载,就像任何其他图片或 iframe 一样。
打印网页时,系统如何处理图片?
网页打印时,所有图片和 iframe 都会立即加载。如需了解详情,请参阅问题 #875403。
Lighthouse 是否会识别浏览器级延迟加载?
Lighthouse 6.0 及更高版本会考虑可使用不同阈值的屏幕外图片延迟加载方法,让这些方法能够通过推迟屏幕外图片审核。
延迟加载图片以提升性能
浏览器支持延迟加载图片后,您可以更轻松地提升网页的性能。
在 Chrome 中启用此功能后,您是否发现了任何异常行为?提交 bug!