原生loading="lazy"必须配合srcset+sizes才能真正优化,因loading仅控制请求时机而不参与选图,单独使用会导致移动端加载大图、流量不省且LCP更差。

原生 loading="lazy" 加 srcset + sizes 是当前最轻量、最可靠、浏览器支持最广的组合,95% 以上现代站点应直接采用;单独用 loading="lazy" 或只配 srcset 都会出问题。
为什么只写 loading="lazy" 会导致移动端加载大图
浏览器对 loading="lazy" 的处理仅控制“何时发起请求”,不参与“选哪张图”。如果只写:
<img src="photo-1200.jpg" loading="lazy" alt="">
那么即使在 iPhone 上,它仍会下载那张 1200px 宽、2MB 的图——只是延迟了 1.5 秒才开始请求。流量没省,LCP 反而更差。
-
loading不读取设备 DPR、不看视口宽度、不解析 media query - 真正决定加载哪张图的是
srcset+sizes的组合逻辑 - 懒加载触发时,浏览器才开始执行
srcset决策;没配就只能 fallback 到src
srcset 和 sizes 必须成对出现,且 sizes 要覆盖全视口范围
sizes 告诉浏览器:“这张图在不同断点下实际占多宽”,缺一不可。漏掉某个区间,浏览器就会回退到默认的 100vw,导致小屏也拉大图。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
sizes="(max-width: 768px) 100vw"→ 缺少769px+区间,桌面端回退为100vw - 正确写法:
sizes="(max-width: 480px) 100vw, (max-width: 1024px) 50vw, 300px"→ 全覆盖 -
srcset中单位必须统一用w(如400w),不能混用x或像素值 -
src应指向最小尺寸图(如photo-400.jpg),作降级兜底,不能留空或指大图
哪些情况 loading="lazy" 会静默失效
它不是“写了就生效”,而是在特定条件下才启用懒加载逻辑;否则浏览器会自动降级为 loading="eager",你完全感知不到。
- 图片没有明确
width和height(设100%或vw也不行)→ Safari 直接忽略 - 父容器用了
transform(如translateZ(0))或overflow: hidden→ Chrome 误判滚动根节点 - 图片由 JS 动态插入(React/Vue 渲染、AJAX 追加)→ 不属于初始 HTML,部分浏览器立即加载
-
loading="lazy"错写在<source>上 → 该属性只对最外层<img>生效
需要兼容老浏览器时,IntersectionObserver 手动实现的关键点
不是所有场景都要手写,但当你必须支持 iOS 15.3 以下、微信 7.x WebView 或 IE 时,IntersectionObserver 是唯一可行的现代方案。
- 真实地址必须存在
data-src(而非src),避免初始请求;加载后赋值并清空data-src - 回调中务必检查
entry.isIntersecting === true,否则滚动停顿可能重复触发 - 加载完成后立刻调用
observer.unobserve(img),否则持续监听已加载图,浪费内存 - 别用
scroll事件轮询:性能差、易漏帧、触发强制同步布局 - 若需提前加载(如滚动前 200px),设
rootMargin: "200px",不要用负值
最容易被忽略的是:首屏关键图(Hero、Logo、头像)必须显式写 loading="eager",不能依赖默认行为——Safari 某些版本会把未声明的图也懒掉,造成白屏。



















