如何实现第二div滚动覆盖第一div的视差滚动效果?
解决滚动时第二个div加速覆盖且向上滚动失效的问题
原代码的核心问题
- 每次滚动事件都调用
getComputedStyle获取top值,会频繁触发浏览器重排,性能低下。 - 计算逻辑错误:当前用当前
top减去scrollY的方式,会导致向上滚动时top值不断异常变小,最终超出预期范围,出现卡住的情况。
优化后的解决方案
基于初始位置和滚动倍数计算第二个div的偏移,同时限制偏移范围确保向上滚动正常回归,再通过requestAnimationFrame减少不必要的计算开销。
完整代码示例
<body> <div class="first-div"></div> <div class="divSecond"></div> <script> const divSecond = document.querySelector(".divSecond"); // 缓存初始top值,仅读取一次避免重复触发重排 const initialTop = parseInt(window.getComputedStyle(divSecond).top); // 滚动速度倍数,大于1表示比页面滚动更快 const scrollSpeedMultiplier = 2; let ticking = false; function updateScrollPosition() { const scrollY = window.scrollY; // 计算偏移量:滚动距离 × (倍数-1),实现加速效果 const offset = scrollY * (scrollSpeedMultiplier - 1); // 限制top值不低于初始位置,确保向上滚动时能回归原位 const newTop = Math.max(initialTop - offset, 0); divSecond.style.top = `${newTop}px`; ticking = false; } window.addEventListener('scroll', function() { if (!ticking) { window.requestAnimationFrame(updateScrollPosition); ticking = true; } }); </script> </body>
* { padding: 0; margin: 0; } body { background-color: black; position: relative; /* 给body设置足够高度,保证可滚动 */ min-height: 200vh; } .first-div { width: 100%; height: 500px; position: absolute; top: 0; background-color: #DE0000; /* 增加背景色方便观察效果 */ } .divSecond { width: 100%; height: 50em; background-color: white; z-index: 2; position: absolute; top: 500px; }
关键优化点说明
- 缓存初始值:仅在初始化时读取一次
divSecond的初始top值,避免重复读取计算样式触发重排。 - 正确加速逻辑:通过
scrollSpeedMultiplier控制滚动速度,比如设为2时,第二个div滚动速度是页面的2倍,偏移量基于滚动距离的差值计算。 - 边界控制:用
Math.max(initialTop - offset, 0)确保top值不会小于0,避免向上滚动时元素过度偏移导致卡住。 - 性能节流:通过
requestAnimationFrame和ticking标记,确保每次浏览器重绘只执行一次位置更新,减少滚动事件的计算压力。
内容的提问来源于stack exchange,提问作者ZombieKicker7
相关产品推荐
相关产品推荐

