📢 新文章推送 · 每周更新优质内容 · 订阅更新 →
向下滚动
技术笔记

网站图片懒加载优化实践

AI 智能总结

为什么要懒加载

图片是网页中最占带宽的资源。如果页面中有 20 张图片,且每张 200KB,首屏就需要下载 4MB 数据。而用户可能只看了前几张就离开了——这意味着大量的带宽和加载时间被浪费了。

懒加载的核心思路是:只加载用户视口内和即将进入视口的图片,其余图片等用户滚动到附近再加载。

原生方案:loading=“lazy”

现代浏览器已原生支持图片懒加载,只需在 <img> 标签添加属性:

1<img src="image.webp" loading="lazy" alt="描述">

Chrome、Firefox、Edge 均已支持。这是最简单的实现,无需 JavaScript。

不足

  • Safari 支持较晚(iOS 15.4+)
  • 无法控制加载阈值(浏览器自行决定何时开始加载)
  • 无法自定义占位图
  • 不支持背景图片懒加载

Intersection Observer 方案

Intersection Observer API 提供了更灵活的控制能力。它会在目标元素进入/离开视口(或指定祖先元素)时触发回调。

基础实现

 1const observer = new IntersectionObserver((entries) => {
 2  entries.forEach(entry => {
 3    if (entry.isIntersecting) {
 4      const img = entry.target;
 5      img.src = img.dataset.src;
 6      img.onload = () => img.classList.add('loaded');
 7      observer.unobserve(img);
 8    }
 9  });
10}, {
11  rootMargin: '200px',    // 提前 200px 开始加载
12  threshold: 0
13});
14
15document.querySelectorAll('img[data-src]').forEach(img => {
16  observer.observe(img);
17});

HTML 结构:

1<img data-src="/images/photo.webp"
2     src="/images/loading.gif"
3     alt="图片描述"
4     class="lazy-img">

关键参数

参数说明
rootMargin视口扩展区域,200px 表示图片在进入视口前 200px 就开始加载
threshold可见比例阈值,0 表示只要有一个像素进入就触发

加载状态

为提升体验,图片通常经历三种状态:

 1.lazy-img {
 2  opacity: 0;
 3  transition: opacity 0.3s ease;
 4  background: #f0f0f0;
 5}
 6.lazy-img.loaded {
 7  opacity: 1;
 8}
 9.lazy-img.error {
10  /* 加载失败时显示 */
11  background: #fff0f0 url('/images/broken.svg') center/48px no-repeat;
12}
  1. 加载中:显示占位图(loading.gif)或骨架屏
  2. 加载完成:透明度过渡动画显示真实图片
  3. 加载失败:显示错误占位图

在 Hugo 中集成

在 Hugo 模板中,通过 shortcode 或自定义 render hook 自动为 Markdown 图片添加懒加载标记:

1{{/* layouts/_default/_markup/render-image.html */}}
2<img data-src="{{ .Destination | safeURL }}"
3     src="/images/loading.gif"
4     alt="{{ .Text }}"
5     class="lazy-img"
6     loading="lazy">

这样所有通过 ![alt](url) 插入的图片都会自动拥有懒加载能力。

性能对比

以一个包含 15 张大图的页面为例:

指标无懒加载原生 loading=“lazy”Intersection Observer
首屏图片请求数153-53-5
首屏图片总大小3.2MB0.6MB0.6MB
LCP 时间4.2s1.8s1.7s
可配置性-

进阶:响应式图片懒加载

结合 <picture> 元素和 srcset,可以实现真正的响应式懒加载:

1<picture>
2  <source data-srcset="/images/photo-800.webp" media="(min-width: 800px)">
3  <source data-srcset="/images/photo-400.webp" media="(min-width: 400px)">
4  <img data-src="/images/photo-200.webp"
5       src="/images/loading.gif"
6       alt="响应式图片"
7       class="lazy-img">
8</picture>

移动端加载小图,桌面端加载大图,进一步节省带宽。

总结

推荐策略:

  • 简单场景:直接使用 loading="lazy" 原生属性
  • 需要精细控制:使用 Intersection Observer,设置 rootMargin 提前加载
  • 最佳实践:两者结合,loading="lazy" 作为兜底,JS 方案做增强
7 / 16
版权声明

本文作者 Lumin

本文链接 https://www.zhengquan.xyz/tech/image-lazy-loading/

许可协议 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

请作者喝杯咖啡 ☕

  • 微信打赏
    微信支付
  • 支付宝打赏
    支付宝
点击按钮查看打赏二维码
🎁 推荐工具
试试这些实用在线工具,提升工作效率
前往工具集 →

留言评论

期待你的想法

评论加载中