由于图片作为 <img>
元素内嵌在 HTML 中,因此可以显示在网页上
或 CSS 背景图片在本博文中,您将了解如何延迟加载这两种类型的图片。
内嵌图片
最常见的延迟加载对象是 <img>
元素中使用的图片。
对于内嵌图片,我们有三种延迟加载选项
以下这些方法可以组合使用,以实现各种浏览器的最佳兼容性:
使用浏览器级延迟加载
Chrome 和 Firefox 都支持使用 loading
属性进行延迟加载。
此属性可添加到 <img>
元素以及 <iframe>
元素。
如果值为 lazy
,则指示浏览器在图片位于视口中时立即加载该图片。
以及在用户滚动至其他图片时获取这些图片。
请参阅 MDN 的 loading
字段
浏览器兼容性
表。
如果浏览器不支持延迟加载,该属性将被忽略
并且图片会立即照常加载
对于大多数网站,向内嵌图片添加此属性可提升性能 并节省用户加载他们可能永远不会滚动到的图片。 如果您有大量图片,并且想确保浏览器用户不支持延迟加载, 则需要将其与下面介绍的某个方法结合使用。
如需了解详情,请参阅适用于网页的浏览器级延迟加载。
使用 Intersection Observer
为了 polyfill 延迟加载 <img>
元素,我们使用 JavaScript 检查这些元素是否在
视口如果是,则其 src
(有时是 srcset
)属性为
填充为所需图片内容的网址。
如果您之前编写过延迟加载代码,那么您可能已经完成了任务
使用 scroll
或 resize
等事件处理脚本。虽然这种方法是
最兼容的所有浏览器,但现代浏览器可提供性能更佳、
通过
Intersection Observer API。
与依赖于各种不同技术的代码相比,Intersection Observer 更易于使用和阅读
因为您只需注册一个观察器即可监控
而无需编写冗长的元素可见性检测代码。全部
剩下要做的就是确定元素可见时该如何操作。
我们假设您的 <img>
元素延迟加载了以下基本标记模式:
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">
您应重点关注此标记的三个相关部分:
class
属性,即您在选择元素时要使用的属性 JavaScript。src
属性,用于引用 。data-src
和data-srcset
属性是占位符属性 ,其中包含元素进入视口后要加载的图片的网址。
现在,我们来看看如何在 JavaScript 中使用 Intersection Observer 进行延迟加载 使用此标记格式的图片:
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Possibly fall back to event handlers here
}
});
在文档的 DOMContentLoaded
事件中,此脚本会向 DOM 查询所有
类为 lazy
的 <img>
元素。如果有 Intersection Observer,
创建一个新的观察器,以在 img.lazy
元素进入
视口
Intersection Observer 适用于所有现代浏览器。
因此,将其用作 loading="lazy"
的 polyfill 可确保大多数访问者都可以使用延迟加载。
CSS 中的图片
虽然 <img>
标记是在网页上使用图片的最常见方式,但图片
也可以通过 CSS 文件调用
background-image
属性(和其他属性)。浏览器级延迟加载不适用于 CSS 背景图片,
因此如果您有要延迟加载的背景图片,则需要考虑其他方法。
与 <img>
元素不同,该元素会随便加载,
CSS 中的图片加载行为是通过更多
猜测。当文档和 CSS 对象
模型
并呈现
树
构建之后,浏览器会先检查 CSS 应用于文档的方式
请求外部资源如果浏览器确定了 CSS 规则
因为涉及外部资源的文档并不适用于当前文档,
浏览器不会请求它。
这种推测行为可用于延迟加载 CSS 中的图片, 使用 JavaScript 确定元素何时位于视口内,以及 随后将一个类应用到该元素,以应用调用 背景图片。这样可以在需要时下载图片 而不是在初始加载时加载例如,假设某个元素包含 大型主打背景图片:
<div class="lazy-background">
<h1>Here's a hero heading to get your attention!</h1>
<p>Here's hero copy to convince you to buy a thing!</p>
<a href="/buy-a-thing">Buy a thing!</a>
</div>
div.lazy-background
元素通常包含主打背景
由某个 CSS 调用的图片。不过,在这个延迟加载示例中,您可以
div.lazy-background
元素的 background-image
属性(通过 visible
)
类:
.lazy-background {
background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}
.lazy-background.visible {
background-image: url("hero.jpg"); /* The final image */
}
接着,使用 JavaScript 检查元素是否在视口中(使用
Intersection Observer!),并将 visible
类添加到
div.lazy-background
元素,用于加载图片:
document.addEventListener("DOMContentLoaded", function() {
var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));
if ("IntersectionObserver" in window) {
let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
lazyBackgroundObserver.unobserve(entry.target);
}
});
});
lazyBackgrounds.forEach(function(lazyBackground) {
lazyBackgroundObserver.observe(lazyBackground);
});
}
});
对 Largest Contentful Paint (LCP) 的影响
延迟加载是一项很好的优化措施,可将图片的加载推迟到实际需要的时间,从而减少启动期间的整体流量消耗和网络争用。这可以缩短启动时间,并通过减少图像解码所需的时间来减少在主线程上的处理。
不过,如果您过于急于使用延迟加载技术,该技术可能会对您网站的 Largest Contentful Paint LCP 产生负面影响。您应避免在启动期间延迟加载视口中的图片。
使用基于 JavaScript 的延迟加载器时,您需要避免延迟加载视口内图片,因为这些解决方案通常使用 data-src
或 data-srcset
属性作为 src
和 srcset
属性的占位符。这里的问题在于,系统会延迟加载这些图片,因为浏览器预加载扫描器在启动期间找不到它们。
即便是使用浏览器级延迟加载来延迟加载视口中的图片,也可能适得其反。对视口内图片应用 loading="lazy"
后,该图片会延迟到浏览器确定它位于视口内,这可能会影响网页的 LCP。
永不在启动期间延迟加载视口中可见的图片。这种模式会对您网站的 LCP 产生负面影响,进而对用户体验产生负面影响。如果启动时需要图片,请在启动时尽快加载,而不要延迟加载!
延迟加载库
您应该尽可能使用浏览器级延迟加载,但如果您发现自己无法采用此方法(例如有大量用户仍依赖于旧版浏览器),则可以使用以下库延迟加载图片:
- lazysizes 是一个功能齐全的延迟视图
用于延迟加载图片和 iframe 的加载库。它使用的模式
它会自动绑定到
lazyload
类,并要求您指定在<img>
data-src
和/或data-srcset
属性,它们的内容交换src
和/或srcset
属性。使用交叉路口 Observer(可对其进行 polyfill 操作),并且可通过 插件 例如延迟加载视频详细了解如何使用 lazysizes。 - vanilla-lazyload 是一个 用于延迟加载图片、背景图片、视频、iframe 和脚本。它利用了 Intersection Observer,支持自适应图片,并且 支持浏览器级延迟加载
- lozad.js 是另一个 选项。因此,它的性能非常出色 但需要先进行 polyfill 操作,然后才能在旧版浏览器上使用。
- 如果您需要 React 专用的延迟加载库,请考虑 react-lazyload。虽然 未使用 Intersection Observer,它提供了一种熟悉的延迟方法, 为习惯于使用 React 开发应用的用户加载图片。