首屏图片加 loading="lazy" 完全无效,浏览器强制立即加载;它仅对滚动后进入视口的非首屏图片生效,错误使用反而拖慢首屏性能。
浏览器规范明确要求:所有在首屏视口内的 <img> 标签,无论是否写了 loading="lazy",都会被强制立即加载。这不是 bug,是设计行为。所以别指望加个属性就能压缩首屏资源体积或减少初始请求数。
常见错误现象包括:页面首屏卡顿、FCP(First Contentful Paint)没改善、Lighthouse 报告里“延迟加载首屏图片”仍标红——其实不是你漏写了 lazy,而是它本来就不该用在这里。
loading="lazy",也照样被忽略<img src="..."> 请求发起时间早于 DOMContentLoaded,且无延迟它只对用户需要滚动后才进入视口的图片生效,核心价值是避免非关键资源抢占带宽和解码线程,间接让首屏渲染更顺畅。
典型适用场景:
立即学习“前端免费学习笔记(深入)”;
details / accordion)内默认隐藏的图片必须满足两个前提才实际推迟请求:
getBoundingClientRect().top > window.innerHeight 或类似判断成立)loading="lazy"(Chrome 76+、Firefox 75+、Edge 79+;Safari 15.4+ 开始有限支持;IE 全系不支持)当 loading="lazy" 被错误地应用于首屏图片,或与 <link rel="preload"> 混用时,可能引发资源竞争,导致关键图片加载被延后。
具体问题:
preload 和 lazy 当作冲突策略处理,部分版本 Chrome 会出现 preload 被降级或丢弃loading="lazy" 和 fetchpriority="high",后者会被忽略,失去优先级提升效果DOMContentLoaded,首屏已滚过,部分图片会“闪现加载”,破坏用户体验正确做法:首屏图片显式声明 loading="eager",或干脆不写该属性(默认行为就是 eager)。
手写 JS 懒加载必须在 DOM 构建完成前就注册监听,否则首屏滚动就错过第一批触发点。
实操建议:
<head> 内并加 defer,确保在 DOMContentLoaded 前执行初始化逻辑window.onload 再调用 new IntersectionObserver(),此时图片可能已完成加载或已滚动出视口data-src 图片,需在 observer callback 中检查 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 来提速。