loading="lazy"仅对满足全部条件的生效:必须在普通文档流中、不在隐藏容器内、属性加在内的最内层上、仅作用于src/srcset图片,不支持background-image,且需chrome 76+/edge 79+/firefox 75+/safari 15.4+。

loading 属性是浏览器原生支持的懒加载方案,无需 JavaScript 就能延迟图片加载,但它的行为和兼容性有明确边界——不是所有 <img> 都适用,也不是所有场景都生效。
哪些图片能用 loading="lazy" 生效
只有满足以下全部条件的 <img> 才会真正懒加载:
- 必须是普通文档流中的图片(不能在
display: none、visibility: hidden或opacity: 0容器内) - 不能在
<picture></picture>内部直接写loading——属性得加在最内层的<img>上,而非<source></source> - 仅对
src或srcset指向的图片起作用;background-image完全不响应该属性 - Chrome 76+、Edge 79+、Firefox 75+、Safari 15.4+ 支持;旧版 Safari(
loading 的三个取值及实际表现
loading 是枚举属性,只接受 "eager"、"lazy"、空字符串(等价于 "eager"),没有 "auto" 或其他值:
-
loading="eager":立即加载,即使图片在视口外(适合关键首屏图) -
loading="lazy":延迟加载,浏览器按内部策略判断何时开始拉取(通常在距离视口约 1250px 时预加载) - 不写该属性:默认行为等同于
loading="eager",不是“自动懒加载”
注意:loading="lazy" 对 <iframe></iframe> 也有效,但本文聚焦图片。
常见失效场景与绕过方式
这些情况会导致 loading="lazy" 形同虚设:
- 图片位于
position: fixed或position: absolute且脱离文档流——浏览器无法计算其滚动位置,直接降级为 eager 加载 - 父容器设置了
overflow: hidden且图片初始不可见——部分 Chrome 版本会误判为“不可滚动区域”,跳过懒加载逻辑 - 使用了
fetchpriority="high":该属性优先级更高,会覆盖loading="lazy",强制提前加载 - 服务端渲染(SSR)时未正确传递
loading属性——比如 Vue/React 中用v-bind或props动态生成却漏传,HTML 源码里根本没这个属性
若必须懒加载上述场景中的图片,只能退回到 IntersectionObserver 手动实现,loading 属性无解。
要不要搭配 decoding="async" 和尺寸属性
可以配,而且推荐配——但它们解决的是不同问题:
-
decoding="async"让图片解码不阻塞主线程,和懒加载正交,加了不会影响loading行为,但能减少卡顿 -
width和height(或style="aspect-ratio")必须设:否则懒加载图片进入视口时可能触发布局偏移(CLS),尤其在响应式页面中 -
srcset+sizes要配齐:否则loading="lazy"可能拉取错误尺寸的图片,浪费带宽
一个稳妥的写法示例:
@@##@@
真正要注意的不是怎么写这个属性,而是理解它不负责“占位”、不控制“解码时机”、也不保证“一定不加载首屏外图片”——它只是告诉浏览器“你可以晚点拉”,而浏览器听不听、什么时候听,取决于当前滚动状态、内存压力和内部启发式算法。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











