图片懒加载的核心逻辑是当图片进入浏览器可视区域时才加载对应的图片资源,避免页面初始化时一次性加载所有图片,从而提升页面加载速度和用户体验。HTML5提供了多种实现图片懒加载的方式,开发者可以根据项目的兼容性要求和功能需求选择合适的方案。

HTML5原生懒加载属性实现
HTML5的img标签新增了loading属性,支持直接设置懒加载,这是最简单的实现方式,不需要编写额外的JavaScript代码。
属性取值说明
- lazy:开启懒加载,图片会在即将进入可视区域时加载
- eager:立即加载,默认值,图片会在页面加载时直接请求资源
- auto:由浏览器自行决定是否懒加载,通常等同于eager
代码示例
<!-- 原生懒加载实现 --> <img src="placeholder.jpg" data-src="https://ipipp.com/images/1.jpg" loading="lazy" alt="示例图片1" width="800" height="400" > <img src="placeholder.jpg" data-src="https://ipipp.com/images/2.jpg" loading="lazy" alt="示例图片2" width="800" height="400" >
这种方式的优点是实现成本极低,浏览器原生支持,不需要额外处理滚动监听逻辑。缺点是兼容性有限,部分旧版本浏览器不支持该属性,如果需要兼容旧环境则不适合使用这种方式。
基于Intersection Observer API实现
Intersection Observer API是HTML5提供的用于监测元素是否进入可视区域的API,相比传统的滚动监听性能更好,不需要频繁触发滚动事件,适合实现自定义懒加载逻辑。
实现思路
- 给所有需要懒加载的图片设置
data-src属性存储真实图片地址,src属性设置占位图 - 创建Intersection Observer实例,设置监测回调和配置项
- 遍历所有懒加载图片,将图片元素添加到Observer的监测列表中
- 当图片进入可视区域时,将
data-src的值赋给src属性,触发图片加载,同时停止监测该图片
完整代码示例
// 获取所有需要懒加载的图片元素
const lazyImages = document.querySelectorAll('img[data-src]');
// 创建Intersection Observer实例
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// 判断元素是否进入可视区域
if (entry.isIntersecting) {
const img = entry.target;
// 将data-src的值赋给src,加载真实图片
img.src = img.dataset.src;
// 加载完成后移除data-src属性
img.removeAttribute('data-src');
// 停止监测当前图片
observer.unobserve(img);
}
});
}, {
// 提前100px触发加载,提升用户体验
rootMargin: '100px'
});
// 遍历所有懒加载图片,添加到监测列表
lazyImages.forEach(img => {
observer.observe(img);
});
对应的HTML结构如下:
<img src="placeholder.jpg" data-src="https://ipipp.com/images/3.jpg" alt="示例图片3" width="800" height="400" > <img src="placeholder.jpg" data-src="https://ipipp.com/images/4.jpg" alt="示例图片4" width="800" height="400" >
这种方式的兼容性比原生loading属性更好,主流现代浏览器都支持,同时可以自定义触发加载的阈值、提前加载的距离等参数,灵活性更高。如果需要兼容IE等不支持该API的旧浏览器,可以引入对应的polyfill库。
传统滚动监听实现方式
在不支持Intersection Observer API的环境下,也可以通过监听页面滚动事件,计算图片位置的方式实现懒加载,不过这种方式需要手动处理性能优化,避免滚动事件频繁触发导致页面卡顿。
实现思路
- 给懒加载图片设置
data-src属性,src设置占位图 - 监听页面的
scroll事件,使用节流函数控制事件触发频率 - 每次触发滚动事件时,遍历所有未加载的懒加载图片,计算图片顶部距离和可视区域底部距离
- 当图片顶部距离小于可视区域底部距离时,加载图片并移除
data-src属性
代码示例
// 节流函数,控制滚动事件触发频率
function throttle(fn, delay) {
let timer = null;
return function() {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
};
}
// 加载懒加载图片的函数
function loadLazyImages() {
// 获取所有未加载的懒加载图片
const lazyImages = document.querySelectorAll('img[data-src]');
// 获取可视区域高度
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
// 获取页面滚动距离
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
lazyImages.forEach(img => {
// 获取图片距离页面顶部的距离
const imgTop = img.getBoundingClientRect().top + scrollTop;
// 如果图片进入可视区域(提前100px触发)
if (imgTop < viewHeight + scrollTop + 100) {
img.src = img.dataset.src;
img.removeAttribute('data-src');
}
});
}
// 初始加载时执行一次
loadLazyImages();
// 监听滚动事件,使用节流控制频率
window.addEventListener('scroll', throttle(loadLazyImages, 200));
这种方式的兼容性最好,几乎所有浏览器都支持,但是需要手动实现节流逻辑,性能不如Intersection Observer API,适合需要兼容非常旧的浏览器的场景。
不同方案对比
| 实现方式 | 实现难度 | 性能表现 | 兼容性 | 适用场景 |
|---|---|---|---|---|
| 原生loading属性 | 极低 | 好 | 一般,现代浏览器支持 | 不需要兼容旧浏览器,追求快速实现的项目 |
| Intersection Observer API | 中等 | 优秀 | 较好,主流现代浏览器支持 | 需要自定义加载逻辑,兼容现代浏览器的项目 |
| 传统滚动监听 | 较高 | 一般,需要手动优化 | 极好,几乎所有浏览器支持 | 需要兼容旧浏览器,无polyfill引入条件的项目 |
在实际开发中,可以根据项目的兼容性要求选择合适的方案,也可以结合多种方案做渐进增强,优先使用原生loading属性,不支持的环境再降级使用Intersection Observer API或者滚动监听方案,兼顾实现成本和兼容性。
HTML5图片懒加载lazy_loadIntersection_Observer修改时间:2026-06-29 20:30:45