页面长列表滚动白屏本质是新进入视口的内容未及时渲染,解决关键在于“保可见”:采用虚拟列表(仅渲染可视区+缓冲项)、transform定位、预计算高度、requestAnimationFrame批处理及骨架屏兜底。

页面长列表滚动时出现白屏,本质不是“滚动卡了”,而是可视区域内容没及时渲染出来——用户快速滑动时,新进入视口的列表项还没生成、定位或绘制,就出现了短暂空白。解决它,关键不在“防卡顿”,而在“保可见”。核心思路是:用最少 DOM + 最快定位 + 零回流重排,让每一帧都稳稳画出内容。
只渲染当前可见区域,彻底砍掉无效 DOM
白屏常发生在滚动加速阶段,因为浏览器还在忙于创建、样式计算、布局大量不可见节点。虚拟列表就是为此而生:
- 不渲染全部 10000 条数据,只渲染当前视口内 + 上下各 3~5 条缓冲项(通常共 20~40 个 DOM)
- 用一个空 div 撑开总高度:
style.height = `${data.length * itemHeight}px`,保证滚动条存在且比例准确 - 滚动时只更新
scrollTop对应的起始索引,动态替换内容区域,不操作整个容器 innerHTML
用 transform 替代 top/padding 定位,避免强制同步布局
如果靠 padding-top 或 top 移动内容区,每次滚动都会触发浏览器检查布局(reflow),造成卡顿甚至丢帧。正确做法是:
- 把所有可见项包裹在一个
<div id="content"> 中<li>用 <code>transform: translateY(${startIndex * itemHeight}px)整体偏移,GPU 加速,不触发布局 - 配合
will-change: transform提前告知浏览器该元素将动画,提升合成效率 - 在 scroll 事件中只做最轻量的事:读
scrollTop,存入变量,然后requestAnimationFrame批处理渲染 - 避免在滚动中调用
getBoundingClientRect()或offsetHeight—— 这些会强制同步布局 - 若列表项高度不固定,用 Pretext 等纯 JS 文本测量库预计算高度,不依赖临时 DOM 插入
- 缓冲区不止上下各 3 条,可设为 8~10 条,确保滚动惯性期间总有内容待命
- 在内容区未就绪前,显示轻量骨架节点(如带 background-color 的 div),宽度/高度与真实项一致,不闪跳
- 首屏加载时,先渲染骨架 + 占位高度,再异步填充数据,避免“突然整块弹出”带来的视觉中断
预计算 + 节流 + requestAnimationFrame,守住主线程
滚动事件高频触发,若每次都在回调里算索引、查数组、建 DOM,主线程立刻过载。必须分层控制:
立即学习“Java免费学习笔记(深入)”;
加缓冲区 + 骨架占位,从感知上消灭白屏
即使逻辑极快,极端快速滑动仍可能漏帧。用户体验层面要兜底:



















