如何使用浏览器原生的懒加载功能设置图片懒加载

如何使用浏览器原生的懒加载功能设置图片懒加载

如何使用浏览器原生的懒加载功能设置图片懒加载

现在,网络支持浏览器级对延迟加载图像的支持!该视频演示了该功能的演示:

从 Chrome 76 开始,你可以使用loading属性来延迟加载图片,而无需编写自定义延迟加载代码或使用单独的 JavaScript 库。让我们深入研究细节。

浏览器兼容性

<img loading=lazy> 大多数流行的 Chromium 驱动的浏览器(Chrome,Edge,Opera)和 Firefox 都支持该功能。WebKit(Safari)的实现正在进行中。 caniuse.com 拥有有关跨浏览器支持的详细信息。不支持该 loading 属性的浏览器只会忽略它而没有副作用。

为什么选择浏览器级的延迟加载?

根据 HTTPArchive 的说法,图像是大多数网站要求最多的资产类型,通常占用的带宽比其他任何资源都要多。在第 90 个百分点,网站在台式机和移动设备上发送大约 4.7 MB 的图像。那是很多猫的照片。

当前,有两种方法可以推迟屏幕外图像的加载:

  • 使用 IntersectionObserver
  • 使用 scrollresizeorientationchange 事件处理程序

任何一种选择都可以使开发人员包括延迟加载功能,并且许多开发人员已经构建了第三方库来提供更易于使用的抽象。由于浏览器直接支持延迟加载,因此不需要外部库。浏览器级的延迟加载还可以确保即使在客户端上禁用了 JavaScript,也可以延迟加载图像。

loading 属性

如今,Chrome 浏览器已经根据图像相对于设备视口的位置以不同的优先级加载图像。视口下方的图像会以较低的优先级加载,但仍会尽快获取。

在 Chrome 76 + 中,你可以使用loading属性完全推迟通过滚动可以访问的屏幕外图像的加载:

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

这是 loading 属性支持的值:

  • auto:浏览器的默认延迟加载行为,与不包含属性的行为相同。
  • lazy:将资源的加载推迟到到达视口的计算距离为止。
  • eager:立即加载资源,而不管其在页面上的位置。

注意: 尽管在 Chromium 中可用,但auto在规范中未提及该值。由于它可能会更改,因此我们建议你在包含它之前不要使用它。

距离窗口的阈值

折叠上方的所有图像(即无需滚动即可立即查看)均正常加载。仅当用户在设备视口附近滚动时,才获取这些视口。

Chromium 的延迟加载实现旨在确保屏幕外的图像加载得足够早,以便在用户滚动到它们附近时完成加载。通过在附近的图像在视口中可见之前获取它们,我们最大化了它们在可见时已被加载的机会。

与 JavaScript 延迟加载库相比,提取滚动到视图中的图像的阈值可能被认为是保守的。铬正在寻求更好地使这些阈值与开发人员的期望保持一致。

使用 Android 上的 Chrome 浏览器进行的实验表明,在 4G 上,懒加载的 97.5%的折叠后图像在可见后 10 毫秒内已完全加载。即使在速度较慢的 2G 网络上,在 10 毫秒内仍可以完全加载 92.6%的折叠图像。这意味着浏览器级别的延迟加载提供了有关滚动到视图中的元素的可见性的稳定体验。

距离阈值不是固定的,并且取决于几个因素:

  • 正在获取的图像资源的类型
  • 是否在 Android 版 Chrome 上启用了精简模式
  • 有效的连接类型

你可以在 Chromium 源中找到不同有效连接类型的默认值。随着 Chrome 小组改进启发式方法来确定何时开始加载,这些数字,甚至仅在距视口一定距离时才获取的方法可能会在不久的将来发生变化。

在 Chrome 77 + 中,你可以通过在 DevTools 中限制网络来尝试使用这些不同的阈值。同时,你将需要使用 chrome://flags/#force-effective-connection-type 标志覆盖浏览器的有效连接类型 。

改进的数据节省和距离从视口的阈值

截至 2020 年 7 月,Chrome 进行了重大改进,以对齐图像延迟加载的视口距离阈值,以更好地满足开发人员的期望。

在快速连接(例如 4G)上,我们将 Chrome 的距视口的距离阈值从降低3000px1250px;在较慢的连接(例如 3G)上,我们将阈值从更改4000px2500px。此更改实现了两件事:

  • <img loading=lazy> 行为更接近 JavaScript 延迟加载库提供的体验。
  • 新的视距距离阈值仍然使我们能够保证在用户滚动到图像时可能已加载图像。

你可以在下面的快速连接(4G)上找到我们的一个演示的旧的与新的视距距离阈值之间的比较:

移动设备上的旧、新的距离阈值
移动设备上的旧、新的距离阈值

为了确保使用最新版本的 Chrome 用户也可以从新的阈值中受益,我们已将这些更改向后移植,以便 Chrome 79-85(含)也使用它们。如果要比较旧版 Chrome 和新版 Chrome 的数据节省情况,请记住这一点。

包含尺寸

浏览器加载图像时,除非明确指定尺寸,否则它不会立即知道图像的尺寸。为了使浏览器能够在页面上为图像保留足够的空间,建议所有<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>标签,无论标签是否被延迟加载。通过延迟加载,这可能变得更加相关。在现代浏览器中对图像进行设置width和设置,height还可以使浏览器推断其固有大小。

如果不包含尺寸,图像仍会延迟加载,但是指定尺寸会降低布局偏移的机会。如果你无法为图像添加尺寸,则延迟加载它们可能会在节省网络资源和可能面临更大版图移位风险之间做出权衡。

尽管 Chromium 中的延迟加载是通过某种方式实现的,以便图像一旦可见就很可能被加载,但仍然有很小的可能尚未加载。在这种情况下,此类图像上的丢失widthheight属性会增加其对 “累积布局偏移” 的影响。

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

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

尽管浏览器将决定从任何<source>元素中加载哪个图像,但该loading 属性仅需要包含在 fallback<img>元素中。

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

你应该避免设置loading=lazy第一个可见视口中的任何图像。

loading=lazy如果可能的话,建议仅添加到折叠以下的图像。渴望加载的图像可以立即获取,而延迟加载的图像则需要浏览器当前等待,直到它知道图像在页面上的位置为止(这依赖于 IntersectionObserver 可用)。

在 Chromium 中,标有的初始视口中的图像在 “loading=lazy最大内容画笔” 上的影响非常小,与热切加载的图像相比,第 75 个百分位数和第 99 个百分位数的回归小于 1%。

通常,应使用浏览器的默认值迅速加载视口内的任何图像。你无需为此指定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 中自动延迟加载图像?

如果在 Android 版 Chrome 浏览器中启用了精简模式,Chromium 已经自动延迟加载任何适合延迟的图像。这主要针对意识到数据节省的用户。

CSS 背景图像可以利用该loading属性吗?

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

延迟加载设备视口内的图像是否有不利之处?

避免放置loading=lazy折叠图片比较安全,因为 Chrome 不会loading=lazy在预加载扫描仪中预加载图片。

loading 属性如何处理视口中但不立即可见的图像(例如:在轮播后面,或对于某些屏幕尺寸被 CSS 隐藏)?

仅按计算的距离延迟加载设备视口以下的图像。视口上方的所有图像,无论是否立即可见,都将正常加载。

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

创建 polyfill 或使用第三方库在你的网站上延迟加载图像。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-srcsrc
  • 如果loading不支持,请加载回退(延迟大小)并启动它。根据 lazysizes 文档,你可以使用 lazyload类作为指示 lazysizes 延迟加载哪些图像的方法。
<!-- 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>

Chrome 是否还支持 iframe 的延迟加载?

<iframe loading=lazy> 最近被标准化,并且已经在 Chromium 中实施。这样一来,你就可以使用 loading 属性来延迟加载 iframe 。

loading属性对 iframe 的影响与对图像的影响不同,具体取决于是否隐藏了 iframe。(隐藏的 iframe 通常用于分析或交流目的。)Chrome 使用以下条件来确定 iframe 是否被隐藏:

  • iframe 的宽度和高度为 4 像素或更小。
  • display: nonevisibility: hidden已应用。
  • 使用负 X 或 Y 定位将 iframe 置于屏幕外。