一、为什么需要图片懒加载?—— 从浏览器加载机制说起
(一)浏览器的「急性子」:图片加载的「堵车现场」
当网页中存在大量图片(如电商网站的 50 + 商品图),浏览器会通过src属性立即发起 HTTP 请求。但浏览器的下载线程有限(不同浏览器并发策略不同,通常 2-10 个),就像狭窄公路突然涌入大量车辆,网络带宽瞬间被抢占,导致首屏加载缓慢,甚至出现「页面卡死」的尴尬局面~
专业简述:浏览器解析 HTML 时,遇到<img src="url">会立即触发网络请求,遵循 HTTP 协议从服务器获取资源。但 TCP/IP 并发连接有限,大量图片同时加载会阻塞关键资源,影响用户体验。
(二)懒加载的核心思想:「按需加载」才是硬道理
懒加载(Lazy Load)的本质是「延迟加载非可视区图片」—— 当图片进入浏览器视口或即将进入时,再触发真实图片的加载。就像外卖小哥不会一次性送完所有订单,而是按用户下单顺序分批配送,既节省带宽又提升效率~
专业简述:通过监听滚动事件或浏览器原生 API,判断图片是否在可视区域内,仅加载用户实际能看到的图片,减少初始加载时的网络请求量。
二、图片懒加载原理全解析 —— 如何让图片「该出现时再出现」
(一)可视区检测:给图片装个「入场感应器」
- getBoundingClientRect() :获取图片相对于视口的位置,判断
top < 视口高度 && bottom > 0,即认为图片进入可视区。
专业简述:该方法返回元素的位置信息(左、右、上、下边界),通过对比视口高度(window.innerHeight),确定是否触发加载逻辑。 - Intersection Observer API(现代浏览器首选):异步监听元素与视口的交集变化,无需频繁计算,性能更优。
专业简述:创建观察者对象,设定阈值(如 10% 进入视口即触发),当图片与视口产生交集时,自动执行加载回调。
(二)占位图与自定义属性:「替身」与「真实身份」的巧妙切换
- 占位图(Placeholder) :初始时
src设置为小尺寸加载图(如 1x1 像素透明图或加载动画),避免空白区域影响布局,同时减少首次请求体积。
专业简述:占位图通常缓存于本地或 CDN,仅需请求一次,确保页面结构稳定,提升用户体验。 - *data-自定义属性:用
data-original存储真实图片地址,避免初始加载时触发请求。当图片进入可视区,通过 JS 将data-original的值赋给src,完成「替身换真」。
专业简述:利用 HTML5 的数据属性规范,解耦图片的展示与加载逻辑,确保初始渲染时不发起无效请求。
三、从 0 到 1 实现图片懒加载 —— 代码实战与最佳实践
(一)基础实现:传统滚动监听方案(兼容旧浏览器)
<!-- HTML结构:占位图+真实地址存储 -->
<img class="lazy"
src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" <!-- 占位图 -->
data-original="https://img.36krcdn.com/hsossms/20250313/v2_15ad8ef9eca34830b4a2e081bbc7f57a@000000_oswg172644oswg1536oswg722_img_000?x-oss-process=image/resize,m_mfit,w_960,h_400,limit_0/crop,w_960,h_400,g_center" <!-- 真实图片地址 -->
alt="示例图">
// 懒加载核心逻辑
function lazyLoad() {
// 获取所有带懒加载标记的图片
const lazyImgs = document.querySelectorAll('img[data-original][lazyload]');
// 获取视口高度(浏览器可见区域高度)
const viewportHeight = window.innerHeight;
lazyImgs.forEach(img => {
// 跳过已加载的图片(无真实地址时直接返回)
if (!img.dataset.original) return;
// 获取图片相对于视口的位置信息
const rect = img.getBoundingClientRect();
// 当图片底部进入视口、顶部未完全离开视口时,触发加载
if (rect.bottom >= 0 && rect.top < viewportHeight) {
// 动态创建img对象预加载真实图片
const tempImg = new Image();
tempImg.src = img.dataset.original;
// 预加载完成后替换src,避免直接赋值导致的闪烁
tempImg.onload = function() {
img.src = img.dataset.original; // 替换为真实图片
img.removeAttribute('data-original'); // 移除标记,避免重复加载
img.removeAttribute('lazyload');
}
}
});
}
// 监听滚动事件(页面滚动时触发懒加载检测)
window.addEventListener('scroll', lazyLoad);
// 页面初始加载时检测一次(首屏图片立即加载)
document.addEventListener('DOMContentLoaded', lazyLoad);
(二)进阶优化:Intersection Observer API 高效实现
现代浏览器推荐使用此方案,无需频繁计算元素位置,性能更优~
function initLazyLoad() {
// 创建观察者实例,配置观察规则
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// 当图片进入视口(交集比例满足阈值)
if (entry.isIntersecting) {
const img = entry.target;
// 预加载真实图片
const tempImg = new Image();
tempImg.src = img.dataset.original;
tempImg.onload = function() {
img.src = img.dataset.original;
img.removeAttribute('data-original');
img.removeAttribute('lazyload');
}
// 加载完成后停止观察(节省性能)
observer.unobserve(img);
}
});
}, {
rootMargin: '200px 0px' // 提前200px开始加载,避免滚动时白屏
});
// 监听所有带懒加载标记的图片
document.querySelectorAll('img[data-original][lazyload]').forEach(img => {
observer.observe(img);
});
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', initLazyLoad);
(三)极简方案:浏览器原生 lazy 属性(适合现代项目)
<!-- 一行代码实现懒加载,浏览器自动处理加载时机 -->
<img src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif"
data-original="https://img.36krcdn.com/hsossms/20250312/v2_aeaa7a1d51e74c3a8f909c96cd73a687@000000_oswg169950oswg1440oswg600_img_jpeg?x-oss-process=image/format,webp"
loading="lazy" <!-- 原生懒加载属性 -->
alt="示例图">
注意:兼容性需考虑(Chrome 77+、Firefox 75 + 支持),旧浏览器会降级为普通加载,建议搭配 JS 方案做渐进增强。
四、避坑指南与性能优化 —— 让懒加载「稳如老狗」
(一)常见问题解决方案
-
图片加载时布局抖动
-
提前设置图片宽高(
width/height)或用 CSS 固定比例:.image-item { width: 100%; height: auto; aspect-ratio: 16/9; /* 保持宽高比,避免布局偏移 */ }
-
-
低网速下图片闪烁
- 占位图使用与真实图片同尺寸的模糊缩略图(如通过 OSS 生成的低清版本),加载完成后平滑过渡。
(二)性能优化技巧
| 优化方向 | 具体方案 |
|---|---|
| 减少无效计算 | 用Intersection Observer替代滚动监听,避免高频触发getBoundingClientRect() |
| 提前加载缓冲 | 设置rootMargin: '200px 0',让图片在距离视口 200px 时开始加载 |
| 图片格式优化 | 真实图片优先使用 WebP/AVIF 格式,占位图用 1x1 像素透明 PNG(体积 < 1KB) |
| 首屏图片特殊处理 | 首屏可见图片不添加懒加载标记,直接通过src加载,避免延迟显示 |
五、总结:懒加载是前端性能优化的「性价比之王」
图片懒加载通过「按需加载」的核心逻辑,在不影响用户体验的前提下,能减少 50% 以上的初始网络请求,尤其适合电商、图库、长文章等图片密集型场景。无论是传统滚动监听、现代 API 还是原生属性,核心都是「让合适的图片在合适的时机出现」。
掌握懒加载不仅能提升网页加载速度,更能体现对用户体验的细节把控 —— 毕竟,没人愿意等一个加载半天的网页,你说对吧~