如何改造现有img懒加载脚本以实现CSS背景图懒加载
兼容CSS背景图场景的懒加载改造方案
改造核心逻辑
原脚本仅支持替换<img>标签的src属性,无法拦截CSS背景图的自动加载请求,核心需要做两点调整:
- 对不同类型的懒加载元素做区分:如果是
<img>标签,赋值给src属性;如果是普通容器(如本次场景里的<span>、<div>等),则把图片路径拼接成url('图片地址')格式,赋值给元素的style.backgroundImage属性。你之前调试版本中,给非图片元素强行赋值src属性的逻辑无实际作用——普通HTML容器的src属性不会被浏览器识别为资源加载地址,不需要保留这类无效赋值 - 避免初始HTML中直接写入真实图片的背景图地址,否则浏览器解析HTML时就会自动发起图片请求,完全绕过懒加载逻辑
第一步:调整对应的HTML结构
将原本直接写在style内联属性里的真实背景图路径移除,替换为data-src属性存储图片真实地址,同时给需要懒加载的元素加上.lazy类:
<div class="col-md-2 col-sm-3 col-xs-4 photo" style="padding: 2.5px"> <span onclick="window.location.href=\''.$link.'\';" class="thumbnail lazy" role="img" style="cursor: pointer; margin: 0; margin-top: 5px; /* 可在此处设置占位背景,如浅灰色块,不要写入真实图片路径 */" aria-label="' . $row["topic_title"] . '" title="'.$row['topic_title'].'" data-src="'.$image.'"> </span> <center> <p class="name" style="margin: 0 2px; color: white; margin-top: 5px;"> <a href="'.$link.'" title="'.$row['topic_title'].'">' . $title . '</a> </p> </center> </div>
注意:原本style里漏写冒号的margin 0 2px要补全为margin: 0 2px,否则样式不会生效。
第二步:替换适配后的完整懒加载脚本
document.addEventListener("DOMContentLoaded", function() { var lazyloadElements; if ("IntersectionObserver" in window) { lazyloadElements = document.querySelectorAll(".lazy"); var elementObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { var targetEl = entry.target; var realSrc = targetEl.dataset.src; // 区分元素类型做不同的加载处理 if (targetEl.tagName === 'IMG') { targetEl.src = realSrc; } else { // 拼接CSS背景图格式的url targetEl.style.backgroundImage = `url('${realSrc}')`; } targetEl.classList.remove("lazy"); elementObserver.unobserve(targetEl); // 移除已经处理完的元素在列表里的引用,减少遍历开销 lazyloadElements = Array.from(lazyloadElements).filter(el => el !== targetEl); } }); }); lazyloadElements.forEach(function(el) { elementObserver.observe(el); }); } else { var lazyloadThrottleTimeout; lazyloadElements = document.querySelectorAll(".lazy"); function lazyload () { if(lazyloadThrottleTimeout) { clearTimeout(lazyloadThrottleTimeout); } lazyloadThrottleTimeout = setTimeout(function() { var scrollTop = window.pageYOffset; lazyloadElements.forEach(function(el) { if(el.offsetTop < (window.innerHeight + scrollTop)) { var realSrc = el.dataset.src; // 和现代浏览器分支保持一致的兼容逻辑 if (el.tagName === 'IMG') { el.src = realSrc; } else { el.style.backgroundImage = `url('${realSrc}')`; } el.classList.remove('lazy'); } }); // 过滤掉已经处理完的元素,避免无效遍历 lazyloadElements = Array.from(lazyloadElements).filter(el => el.classList.contains('lazy')); if(lazyloadElements.length == 0) { document.removeEventListener("scroll", lazyload); window.removeEventListener("resize", lazyload); window.removeEventListener("orientationChange", lazyload); } }, 20); } document.addEventListener("scroll", lazyload); window.addEventListener("resize", lazyload); window.addEventListener("orientationChange", lazyload); } })
常见注意事项
- 必须给所有使用CSS背景图的懒加载容器设置明确的宽高,否则初始状态下元素高度为0,可能被误判为已经进入可视区,失去懒加载效果
- 图片路径拼接时要做转义处理,避免路径中包含单引号导致的样式失效问题
- 改造后首屏加载时,只有可视区域内的图片会发起请求,其余滚动到可视范围才触发下载,可大幅降低多gif场景下的首屏加载耗时
内容的提问来源于stack exchange,提问作者Andrei Gradinaru
相关产品推荐
相关产品推荐

