12k
All articles

仅使用 HTML 实现原生图片懒加载

通过 loading 属性实现原生 HTML 懒加载,无需 JavaScript 即可延迟加载图片,正确使用可提升性能并防止布局偏移。

OpenReplay Team
OpenReplay Team
仅使用 HTML 实现原生图片懒加载

Web 开发者不断寻求优化页面性能的方法,而图片往往是最大的挑战。虽然 JavaScript 库多年来一直主导着懒加载解决方案,但现代浏览器现在通过简单的 HTML 属性支持原生图片懒加载。这种内置功能消除了对外部依赖的需求,同时在所有主流浏览器中提供可靠的性能改进。

本文将解释如何仅使用 HTML 实现原生图片懒加载,涵盖浏览器支持、最佳实践以及可能影响网站性能的常见陷阱。

关键要点

  • 原生懒加载只需要 loading="lazy" HTML 属性
  • 始终指定 width 和 height 属性以防止布局偏移
  • 永远不要对首屏或 LCP 图片使用懒加载
  • 浏览器支持覆盖 95%+ 的用户,包括 Chrome、Firefox、Safari 和 Edge
  • 图片在达到计算的距离阈值时自动加载
  • 无需 JavaScript,但可以使用回退方案扩展浏览器支持
  • 性能改进通常带来 20-50% 的初始加载时间提升

什么是原生图片懒加载?

原生图片懒加载利用浏览器的内置能力,将图片加载推迟到需要时才进行。浏览器不会在页面首次渲染时加载所有图片,而是计算图片何时进入视口,并在它们即将可见之前加载它们。

这种方法与基于 JavaScript 的解决方案不同,因为它:

  • 无需额外的代码或库
  • 即使在 JavaScript 被禁用时也能工作
  • 使用优化的浏览器算法进行加载决策
  • 在不同设备和连接速度下提供一致的行为

浏览器自动处理关于视口距离、连接速度和加载阈值的所有复杂计算。

原生懒加载的浏览器支持

当前 loading 属性的浏览器支持覆盖所有主流浏览器:

  • Chrome:77+(2019年9月)
  • Firefox:75+(2020年4月)
  • Safari:15.4+(2022年3月)
  • Edge:79+(2020年1月)

这代表了超过 95% 的全球浏览器使用量,使原生懒加载成为大多数网站的可靠选择。不支持该属性的浏览器会简单地忽略它,正常加载图片而不会产生任何负面影响。

Loading 属性:核心实现

loading 属性接受三个值:

lazy

延迟加载直到图片达到与视口的计算距离:

<img src="product-image.jpg" loading="lazy" alt="Product description" width="400" height="300">

eager

强制立即加载,无论视口位置如何(这是默认行为):

<img src="hero-image.jpg" loading="eager" alt="Hero section" width="800" height="400">

auto(已弃用)

之前允许浏览器决定,但此值已被弃用,不应使用。

基本最佳实践

始终包含尺寸

实现原生图片懒加载最关键的方面是指定图片尺寸。没有 width 和 height 属性,浏览器无法为图片保留空间,导致布局偏移:

<!-- 正确实现 -->
<img src="gallery-1.jpg" loading="lazy" alt="Gallery image" width="300" height="200">

<!-- 使用内联样式的替代方案 -->
<img src="gallery-2.jpg" loading="lazy" alt="Gallery image" style="width: 300px; height: 200px;">

当未指定尺寸时,图片默认为 0×0 像素。这可能导致浏览器假设所有图片都适合视口,触发立即加载所有内容。

永远不要对首屏图片使用懒加载

在初始页面加载期间可见的关键图片永远不应使用 loading="lazy"。这包括:

  • 英雄图片
  • Logo 图片
  • 前几个产品图片
  • 初始视口中的任何图片
<!-- 首屏图片 - 立即加载 -->
<img src="hero-banner.jpg" alt="Main banner" width="1200" height="600">
<img src="featured-product.jpg" alt="Featured item" width="400" height="300">

<!-- 首屏以下图片 - 懒加载 -->
<img src="product-4.jpg" loading="lazy" alt="Product 4" width="400" height="300">
<img src="product-5.jpg" loading="lazy" alt="Product 5" width="400" height="300">

响应式图片的懒加载

对于使用 <picture> 元素的响应式图片,只需在回退的 <img> 元素上添加 loading 属性:

<picture>
  <source media="(min-width: 800px)" srcset="large-image.jpg 1x, large-image-2x.jpg 2x">
  <source media="(min-width: 400px)" srcset="medium-image.jpg 1x, medium-image-2x.jpg 2x">
  <img src="small-image.jpg" loading="lazy" alt="Responsive image" width="400" height="300">
</picture>

浏览器距离阈值的工作原理

浏览器不会等到图片完全进入视口才开始加载它们。相反,它们使用基于连接速度的距离阈值:

  • 4G 连接:图片在距离视口约 1,250px 时开始加载
  • 3G 及更慢连接:图片在距离视口约 2,500px 时开始加载

这些阈值确保图片在用户滚动到它们之前完成加载。在测试中,97.5% 的 4G 网络懒加载图片在变为可见的 10ms 内完全加载。

常见实现挑战

防止布局偏移

没有适当的尺寸,懒加载可能会增加累积布局偏移(CLS)。始终指定确切尺寸或使用 CSS 维持宽高比:

.lazy-image {
  width: 100%;
  height: auto;
  aspect-ratio: 16/9;
}

隐藏图片

在 Chrome、Safari 和 Firefox 中,使用 display: none 的图片不会懒加载。但是,使用 opacity: 0visibility: hidden 隐藏的图片仍会加载。彻底测试您的实现:

<!-- 不会懒加载 -->
<img src="hidden.jpg" loading="lazy" style="display: none;">

<!-- 会懒加载 -->
<img src="hidden.jpg" loading="lazy" style="opacity: 0;">

轮播和滑块图片

Chrome 121 改变了水平滚动图片的行为。轮播图片现在使用与垂直滚动相同的阈值,意味着它们在变为可见之前加载。这改善了用户体验但增加了带宽使用。

旧版浏览器的 JavaScript 回退

为了更广泛的浏览器支持,实现渐进增强方法:

<!-- 带回退的懒加载 -->
<img data-src="image.jpg" loading="lazy" alt="Description" width="400" height="300" class="lazy-fallback">

<script>
if ('loading' in HTMLImageElement.prototype) {
  // 支持原生懒加载
  const images = document.querySelectorAll('img[loading="lazy"]');
  images.forEach(img => {
    img.src = img.dataset.src;
  });
} else {
  // 加载回退库
  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>

性能影响和指标

实现原生图片懒加载通常带来:

  • 初始页面加载时间减少 20-50%
  • 带宽使用量减少 30-60%
  • 改善核心 Web 指标得分
  • 在较慢连接上提供更好的用户体验

使用浏览器开发者工具和性能监控服务(如 PageSpeed InsightsWebPageTest)监控您的实现。

测试您的实现

浏览器开发者工具

使用 Chrome DevTools 验证懒加载:

  1. 打开 DevTools(F12)
  2. 转到 Network 选项卡
  3. 按”Img”过滤
  4. 重新加载页面并慢慢滚动
  5. 观察图片在接近视口时加载

网络限制

测试不同的连接速度:

  1. 在 DevTools 中,转到 Network 选项卡
  2. 从限制下拉菜单中选择”Slow 3G”或”Fast 3G”
  3. 观察加载阈值如何变化

边缘情况和限制

打印行为

当用户打印页面时,所有图片都会立即加载,无论 loading 属性如何。这确保打印的文档包含所有图片。

SEO 考虑

搜索引擎爬虫可以无问题地访问懒加载图片。loading 属性不会对 SEO 产生负面影响,更快的页面加载可以改善搜索排名。

背景图片

loading 属性只适用于 <img><iframe> 元素。对于背景图片,您需要使用 Intersection Observer API 的 JavaScript 解决方案。

结论

原生图片懒加载提供了一种简单、有效的方法来改善页面性能,无需外部依赖。通过在首屏以下图片上添加 loading="lazy" 属性并遵循关于尺寸和视口考虑的最佳实践,您可以显著减少初始页面加载时间和带宽使用。

成功实现的关键在于理解何时使用懒加载、始终指定图片尺寸,以及在不同设备和连接速度下进行测试。凭借广泛的浏览器支持和零开销,原生懒加载应该成为每个前端开发者性能优化工具包的一部分。

常见问题

什么是原生图片懒加载,它是如何工作的?

原生图片懒加载是一种浏览器功能,使用 HTML loading 属性将图片加载推迟到需要时才进行。浏览器根据连接速度和距离阈值计算图片何时进入视口,然后在它们对用户可见之前加载它们。

哪些浏览器支持懒加载的 loading 属性?

所有主流现代浏览器都支持原生懒加载,包括 Chrome 77+、Firefox 75+、Safari 15.4+ 和 Edge 79+。这代表了超过 95% 的全球浏览器使用量。不支持该属性的浏览器会简单地忽略它并正常加载图片。

使用 loading lazy 时需要指定图片尺寸吗?

是的,使用 loading lazy 时始终包含 width 和 height 属性。没有尺寸,浏览器无法为图片保留空间,导致布局偏移和潜在问题,浏览器可能假设所有图片都适合视口并立即加载所有内容。

我应该在网站的所有图片上使用 loading lazy 吗?

不,永远不要在首屏图片上使用 loading lazy,特别是在初始页面加载期间可见的 LCP 图片。只对出现在首屏以下或初始视口外的图片应用懒加载,以避免减慢关键内容渲染。

如果我在用 CSS 隐藏的图片上使用 loading lazy 会发生什么?

行为取决于图片的隐藏方式。在大多数浏览器中,使用 display none 的图片不会懒加载,而使用 opacity 0 或 visibility hidden 隐藏的图片仍会加载。始终彻底测试您的实现以确保它按预期行为。

Listen to your bugs 🧘, with OpenReplay

See how users use your app and resolve issues fast.
Loved by thousands of developers

We use cookies to improve your experience. By using our site, you accept cookies.