loading="lazy"在Chrome 76+、Firefox 75+、Edge 79+及Safari 15.4+(仅img)中生效,但受src非空、图片不在首屏、有宽高属性、父容器可见等条件限制,且不提供加载状态反馈。

loading="lazy" 在现代浏览器中是原生支持的,但不是“写了就懒”,它有明确的生效边界和一堆静默失效的坑。
哪些浏览器真正认 loading="lazy"
Chrome 76+、Firefox 75+、Edge 79+ 全量支持 loading="lazy",且对 <img> 和 <iframe> 都有效;Safari 从 15.4 开始支持,但仅限 <img>,且早期版本(15.4–16.3)存在滚动抖动 bug,16.4+ 已修复。iOS Safari 15.3 及更早、微信旧版 X5 WebView 完全忽略该属性,不报错也不生效。
验证方式:打开 Chrome DevTools → Network → 刷新页面 → 滚动观察图片请求是否随视口进入而分批出现;若首屏外图片在初始请求列表里就全量加载,说明没生效。
为什么加了 loading="lazy" 却还是立刻加载
常见原因不是语法错,而是结构或环境不满足前提:
立即学习“前端免费学习笔记(深入)”;
-
src为空、是data:URL 或 JS 动态插入后才赋值——浏览器只在 HTML 解析阶段读取该属性,后续改src不触发原生逻辑 - 图片初始就在视口内(比如页面高度<一屏,或图片紧贴
<body>顶部)——浏览器认为“已可见”,直接加载 - 缺少
width和height属性,或 CSS 未设固定尺寸(aspect-ratio在 Safari 15.4+ 才可用)——部分浏览器(如 Safari)会降级为eager - 父容器用了
display: none、visibility: hidden、transform、opacity: 0——脱离 layout 流,浏览器无法计算位置 -
loading="lazy"写在<picture>或<source>上——必须写在最内层<img>标签上
loading="eager" 和不写 loading 属性有区别吗
没有实质区别:loading="eager" 是显式声明,不写则默认行为就是 eager。但显式写出来有两点实际价值:
- 避免 CMS/富文本编辑器过滤掉空或非法
loading值(比如过滤掉loading=""后变成无属性,反而可能被某些旧引擎误判) - 首屏关键图(banner、logo、操作按钮图标)必须用
loading="eager"或干脆不写——否则在低性能设备、后台标签页、或 SSR hydration 前,可能出现白屏或 CLS(布局偏移) - 不能把所有图片都设为
lazy:瀑布流中用户快速下滑时,原生提前量约 1250px,可能跟不上滚动节奏,导致“图片逐个弹出”;此时需用IntersectionObserver配rootMargin: "200px"手动控制
配合 srcset/sizes 使用时容易踩的坑
loading="lazy" 和响应式图片是正交能力,但协同不好会引发重复请求或资源错配:
- 必须同时提供
sizes,否则浏览器无法预估当前视口宽度下的图片渲染宽度,可能从srcset中选错资源,甚至重复请求同一张图 - 错误示例:
<img src="a.jpg" srcset="a-480w.jpg 480w, a-1024w.jpg 1024w" loading="lazy">—— 缺sizes,行为不可控 - 正确写法:
<img src="a.jpg" srcset="a-480w.jpg 480w, a-1024w.jpg 1024w" sizes="(max-width: 480px) 480px, 1024px" loading="lazy"> -
srcset中某项路径 404?fallback 机制不稳定,图片可能直接不显示,建议服务端校验资源可用性
最关键的一点:原生 loading="lazy" 不提供加载状态反馈,也没失败重试、占位图切换、渐入动画这些能力——如果业务需要这些,就得上 IntersectionObserver,而不是硬凑 loading="lazy" + JS 补丁,否则容易触发重复加载或竞态问题。



















