在首屏图片上添加 loading="lazy" 属性实际上并不会延迟加载,因为浏览器会强制立即加载这些图片。这并非浏览器缺陷,而是HTML规范的有意设计。懒加载仅对用户滚动后进入视口的非首屏图片生效,错误使用反而会拖慢首屏渲染速度。

loading="lazy" 对首屏图片完全无效
浏览器规范明确:所有位于首屏视口内的 标签,无论是否添加 loading="lazy",都会被强制立即加载。这并非设计缺陷,而是规范有意为之。因此,不要指望通过添加该属性来压缩首屏资源体积或减少初始请求数。
常见的错误表现包括:页面首屏加载卡顿、FCP(First Contentful Paint)未得到改善、Lighthouse 审核报告中“延迟加载首屏图片”项依然标红。实际上,问题不在于忘记添加 lazy 属性,而在于该属性根本不应在此处使用。
- 首屏的判定由浏览器在运行时完成,取决于设备DPR、视口宽高、滚动位置等因素,并非简单地按HTML顺序计算前N张图片
- 在服务端渲染(SSR)或静态生成(SSG)页面中,即使首屏图片被服务端注入了
loading="lazy",浏览器同样会忽略该属性 - 在Chrome DevTools的Network面板中可以清晰观察到:首屏图片的请求发起时间早于
DOMContentLoaded事件,且没有任何延迟
懒加载真正起效的场景和条件
懒加载仅对用户滚动后进入视口的图片生效,其核心价值在于避免非关键资源抢占带宽和解码线程,从而间接提升首屏渲染的流畅度。
典型适用场景:
- 长图文流(例如新闻列表、博客文章中的插图)
- 页面底部的轮播图、相关推荐模块
- 折叠区域(如
details、accordion)内默认隐藏的图片 - 分页加载的无限滚动列表(后续页面的图片)
但必须满足两个前提,才会实际推迟请求:
- 图片不在初始视口内(即满足
getBoundingClientRect().top > window.innerHeight或类似条件) - 浏览器支持
loading="lazy"(Chrome 76及以上、Firefox 75及以上、Edge 79及以上;Safari 15.4及以上开始有限支持;IE全系列不支持)
用错 lazy 反而拖慢首屏速度
当 loading="lazy" 被错误地应用于首屏图片,或与 混合使用时,可能引发资源竞争,导致关键图片的加载被延迟。
具体问题:
- 浏览器内部的资源调度器会将
preload与lazy视为冲突策略,在某些Chrome版本中,preload可能被降级或丢弃 - 如果首屏图片同时带有
loading="lazy"和fetchpriority="high",则fetchpriority="high"会被忽略,无法起到优先级提升的作用 - 使用 IntersectionObserver 手动实现懒加载时,如果初始化晚于
DOMContentLoaded,首屏滚动可能已经发生,部分图片会出现“闪现加载”现象,影响用户体验
正确做法是:为首屏图片显式声明 loading="eager",或者干脆不写该属性(因为默认行为就是 eager)。
兼容旧浏览器时 IntersectionObserver 的初始化时机很关键
手动实现JS懒加载时,必须在DOM构建完成之前注册监听器,否则首屏滚动可能会错过第一批触发点。
实操建议:
- 将脚本放在
中并添加defer属性,确保在DOMContentLoaded事件触发前执行初始化逻辑 - 不要等到
window.onload事件才调用new IntersectionObserver(),因为此时图片可能已经完成加载或已滚动出视口 - 对于
data-src图片,需要在 observer 回调中检查isIntersecting === true后再赋值img.src,并移除data-src属性以防止重复触发
示例关键片段:
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
}, { threshold: 0.1 });
将 threshold 设置为 0.1 表示元素 10% 进入视口即触发,比默认值 0 响应更早,避免用户刚看到图片边缘才开始加载。
首屏性能优化是一个系统工程,懒加载只是其中一环;它不解决首屏资源本身的下载问题,只管理非关键资源的加载节奏。最容易被忽略的一点是:首屏图片永远不应添加 loading="lazy",而应通过压缩格式、CDN、响应式 sizes/srcset 以及内联关键CSS来提升速度。
