
本文介绍如何通过监听 wheel 事件并阻止默认滚动行为,实现一个容器(如左栏)的鼠标滚轮操作精准驱动另一个容器(如右栏)的滚动,同时支持平滑过渡与边界控制。
本文介绍如何通过监听 `wheel` 事件并阻止默认滚动行为,实现一个容器(如左栏)的鼠标滚轮操作精准驱动另一个容器(如右栏)的滚动,同时支持平滑过渡与边界控制。
在构建双栏布局(例如图文对照、侧边导航+主内容)时,常需实现“滚动联动”效果:用户在左栏滚动时,不触发自身滚动,而是驱动右栏内容平滑滚动;当右栏到底部后,再继续滚动才触发页面整体滚动(如显示页脚)。原始代码中使用 scroll 事件监听 + 同步 scrollTop 的方式存在根本性缺陷——它依赖左栏实际发生滚动,而左栏若内容不足或未启用滚动,该机制即失效。
正确方案是拦截滚轮输入(wheel 事件),主动计算并应用滚动偏移量。以下是分步实现:
✅ 基础联动(即时响应)
document.addEventListener('DOMContentLoaded', () => {
const column1 = document.getElementById('column-1');
const column2 = document.getElementById('column-2');
column1.addEventListener('wheel', (ev) => {
// 将左栏的滚轮位移 deltaY 应用到右栏
column2.scrollTop += ev.deltaY;
// 阻止左栏自身滚动(关键!)
ev.preventDefault();
}, { passive: false }); // passive: false 是必须的,否则 preventDefault() 无效
});
⚠️ 注意:{ passive: false } 选项不可或缺。现代浏览器默认将 wheel 设为 passive,此时调用 ev.preventDefault() 会被忽略,导致左栏仍会滚动。
✅ 平滑滚动(消除抖动)
基础版滚动生硬、有跳跃感。可通过简易物理模拟(阻尼减速)实现自然惯性效果:
let scrollSpeed = 0;
let lastTime = 0;
const SPEED_FACTOR = 4; // 调小则更灵敏,调大则更缓和
column1.addEventListener('wheel', (ev) => {
scrollSpeed = ev.deltaY / SPEED_FACTOR;
ev.preventDefault();
}, { passive: false });
function update(deltaTime) {
// 每帧按指数衰减速度(模拟摩擦力)
scrollSpeed *= 0.92;
}
function render() {
column2.scrollTop += scrollSpeed;
// 边界限制:防止滚动超出范围
const maxScroll = column2.scrollHeight - column2.clientHeight;
column2.scrollTop = Math.max(0, Math.min(maxScroll, column2.scrollTop));
}
function gameLoop(timestamp) {
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
update(deltaTime);
render();
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
✅ 关键 CSS 保障
确保两栏具备独立滚动能力且高度可控:
.column-1, .column-2 {
width: 50%;
overflow-y: auto; /* 必须显式启用垂直滚动 */
max-height: 100vh; /* 防止内容撑开容器 */
}
.content {
display: flex;
height: 100vh; /* 使父容器占满视口 */
overflow: hidden; /* 避免 body 再次出现滚动条 */
}
? 最终行为逻辑
- 用户在左栏(#column-1)滚动 → 左栏不滚动,右栏(#column-2)按比例滚动;
- 右栏滚动至顶部/底部时自动吸附,不越界;
- 右栏滚动结束后,若继续滚动,可结合 scrollend 事件(或监听 scrollTop 达极值)移交控制权给 body 或 footer,实现“先内容后页脚”的自然浏览流。
此方案解耦了滚动源与目标,兼顾性能与体验,适用于产品介绍页、数字画册、文档对照等场景。











