为什么需要图片懒加载
图片是网页中体积最大的资源类型之一。根据 HTTP Archive 的统计,图片平均占网页总重量的 50% 以上。在一个典型的新闻或电商页面中,可能有数十张图片同时加载,这会导致首屏加载时间显著增加、带宽浪费和数据流量消耗。图片懒加载(Lazy Loading)的核心思想是:只加载用户当前可见区域(视口)内的图片,其他图片在用户滚动到附近时才加载。这种方法可以大幅减少初始页面加载时间,提升用户体验和核心 Web 指标(Core Web Vitals)。
一、技术概述
1.1 工作原理
懒加载的技术实现基于以下几个关键步骤:
- 替换图片源:在 HTML 中,将
<img>标签的src属性替换为占位图或空白,并将真实图片 URL 存储在data-src等自定义属性中 - 监测滚动位置:监听页面滚动事件,或使用 Intersection Observer API 监测图片元素是否进入视口
- 加载真实图片:当图片进入视口时,将
data-src的值赋给src属性,触发浏览器加载 - 加载完成处理:图片加载完成后,移除占位样式,显示真实图片
1.2 性能收益
| 场景 | 未使用懒加载 | 使用懒加载 | 提升 |
|---|---|---|---|
| 首屏加载时间 | 3.5s | 1.8s | 提升 48% |
| 页面总传输量 | 2.8MB | 0.6MB | 减少 78% |
| Lighthouse Performance 评分 | 62 | 94 | 提升 32 分 |
二、实现方案
2.1 原生懒加载(推荐)
从 Chrome 76 开始,浏览器原生支持图片懒加载,只需在 <img> 标签中添加 loading="lazy" 属性:
<img src="example.jpg" loading="lazy" alt="示例图片" />
<!-- 支持 iframe 懒加载 -->
<iframe src="example.html" loading="lazy"></iframe>
优点:零 JavaScript 代码,浏览器自动优化加载时机,性能最佳。
缺点:不支持所有浏览器(Safari 需 15.4+)。
2.2 Intersection Observer API
对于需要更精细控制的场景,可以使用 Intersection Observer API:
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});
document.querySelectorAll('img.lazy').forEach(img => {
imageObserver.observe(img);
});
| 方案 | 复杂度 | 性能 | 可维护性 | 适用场景 |
|---|---|---|---|---|
| 原生 lazy 属性 | 低 | 极高 | 高 | 通用场景 |
| Intersection Observer | 中 | 高 | 中 | 需要自定义加载效果 |
| 第三方 JS 库 | 低 | 中 | 中 | 兼容老旧浏览器 |
2.3 第三方库方案
- Lozad.js:轻量级(1KB),基于 Intersection Observer
- lazysizes:功能最全,支持响应式图片和自动计算
- vanilla-lazyload:简单易用,支持图片、iframe 和视频
三、高级优化技巧
// 结合占位图技术(BlurHash)
const img = new Image();
img.onload = () => {
// 先显示模糊缩略图
placeholder.style.filter = 'blur(20px)';
// 加载完成后淡入高清图
highResImg.classList.add('loaded');
};
img.src = highResUrl;
四、注意事项
- 首屏图片不应用懒加载:首屏可视区域内的图片应使用正常加载
- 预留图片占位空间:设置宽高比(aspect-ratio)防止布局偏移
- 考虑 SEO 影响:确保搜索引擎爬虫能抓取到图片
- 兼容性处理:为不支持原生懒加载的浏览器提供降级方案
- 图片解码优化:使用
decoding="async"属性异步解码图片
五、总结
图片懒加载是提升网页性能最简单有效的优化手段之一。对于现代浏览器,推荐直接使用 loading="lazy" 属性;如果需要自定义加载效果或支持更多功能,Intersection Observer API 提供了足够的灵活性和性能。无论采用哪种方案,合理配置懒加载都能显著改善用户体验和核心性能指标。