如何实现HTML卡片懒加载,滚动时渲染且首张卡片始终保持显示?
卡片滚动懒加载实现方案
核心实现思路
- 页面初始化时仅渲染首张卡片,其余卡片先用等高占位符占据文档流位置,避免滚动时高度突变
- 监听未渲染卡片占位符的可视状态,当占位符进入视口范围时,再把对应卡片的真实内容替换到DOM中
原生JS实现方案(无需第三方依赖,性能最优)
第一步:编写HTML结构
<div class="card-wrapper"> <!-- 首张卡片默认直接渲染 --> <div class="card"> <h3>首张卡片标题</h3> <p>首张卡片的具体内容</p> </div> <!-- 其余卡片先用占位符占位,卡片内容可以存在data属性或者JS数组中 --> <div class="card-placeholder" data-index="1"></div> <div class="card-placeholder" data-index="2"></div> <div class="card-placeholder" data-index="3"></div> <!-- 更多卡片占位符 --> </div>
第二步:编写基础CSS
/* 真实卡片样式 */ .card { height: 420px; margin-bottom: 24px; padding: 20px; border-radius: 12px; border: 1px solid #e5e7eb; box-sizing: border-box; } /* 占位符样式,高度和真实卡片保持一致 */ .card-placeholder { height: 420px; margin-bottom: 24px; border-radius: 12px; background-color: #f3f4f6; }
第三步:编写JS逻辑(使用Intersection Observer API)
// 预设的卡片数据,按索引对应 const cardData = [ {title: "第二张卡片", content: "第二张卡片的内容"}, {title: "第三张卡片", content: "第三张卡片的内容"}, {title: "第四张卡片", content: "第四张卡片的内容"}, ] const placeholders = document.querySelectorAll(".card-placeholder") // 创建观察器实例 const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { // 占位符进入视口时触发渲染 if(entry.isIntersecting) { const placeholder = entry.target const index = Number(placeholder.dataset.index) const currentCardData = cardData[index] // 生成真实卡片 const card = document.createElement("div") card.className = "card" card.innerHTML = ` <h3>${currentCardData.title}</h3> <p>${currentCardData.content}</p> ` // 替换占位符 placeholder.replaceWith(card) // 移除已渲染元素的观察 observer.unobserve(placeholder) } }) }, { rootMargin: "150px 0", // 提前150px预加载,用户滚动到对应位置时已完成渲染,无感知 threshold: 0.1 }) // 给所有占位符绑定观察 placeholders.forEach(item => observer.observe(item))
可选优化点
- 如果卡片内包含图片,给图片标签加上原生
loading="lazy"属性,实现图片层级的懒加载 - 卡片总数大于20个时可以做分批加载,避免初始化时生成太多占位符DOM节点影响性能
- 要兼容IE等极低版本浏览器的话,可以降级为监听scroll事件,通过
getBoundingClientRect()计算占位符位置判断是否进入视口
内容的提问来源于stack exchange,提问作者Rafaell444
相关产品推荐
相关产品推荐

