
本文介绍如何通过原生 JavaScript 和 CSS 实现“一屏一节”的平滑滚动效果:用户每次滚轮操作仅切换一个全屏高度的 section,避免内容遗漏,兼容鼠标滚轮、触控板及 Magic Mouse。
本文介绍如何通过原生 JavaScript 和 CSS 实现“一屏一节”的平滑滚动效果:用户每次滚轮操作仅切换一个全屏高度的 section,避免内容遗漏,兼容鼠标滚轮、触控板及 Magic Mouse。
要实现精准的“单节滚动”(也称“分页式滚动”或 “scroll snapping”),核心在于拦截默认滚动行为,主动控制视口定位到指定 section 的顶部。以下是一套稳定、跨设备兼容的解决方案,无需第三方库,适用于现代浏览器(Chrome/Firefox/Safari/Edge)。
✅ 关键实现逻辑
- 使用 wheel 事件监听滚轮方向与幅度;
- 通过 event.wheelDelta、event.deltaY 或 event.detail 统一归一化滚动方向(向上为正,向下为负);
- 维护当前激活的 section 索引(currentSection),限制边界(不能小于 0 或超过最大索引);
- 调用 window.scrollTo({ top: target.offsetTop, behavior: 'smooth' }) 实现平滑跳转。
? 完整代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>单节滚动教程</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
margin: 0;
overflow: hidden; /* 隐藏全局滚动条,由 JS 控制 */
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.container {
height: 400vh; /* 确保容器足够高以容纳所有 section */
}
.sections {
height: 100vh; /* 每个 section 占满视口高度 */
display: flex;
justify-content: center;
align-items: center;
font-size: 2.5rem;
font-weight: bold;
color: #333;
scroll-snap-align: start; /* 辅助原生 scroll-snap(可选增强) */
}
/* 各 section 背景色区分 */
#sectionOne { background-color: #ffecd2; }
#sectionTwo { background-color: #d1ecff; }
#sectionThree { background-color: #e2f0cb; }
#sectionFour { background-color: #f8d7da; }
</style>
</head>
<body>
<div class="container">
<div class="sections" id="sectionOne"><p>DIV 1</p></div>
<div class="sections" id="sectionTwo"><p>DIV 2</p></div>
<div class="sections" id="sectionThree"><p>DIV 3</p></div>
<div class="sections" id="sectionFour"><p>DIV 4</p></div>
</div>
<script>
let currentSection = 0;
const sections = document.querySelectorAll('.sections');
const totalSections = sections.length;
function handleWheel(event) {
// 归一化滚轮方向:向上滚动 → delta > 0;向下 → delta < 0
const delta = event.wheelDelta || -event.deltaY || -event.detail;
if (delta > 0 && currentSection > 0) {
currentSection--;
} else if (delta < 0 && currentSection < totalSections - 1) {
currentSection++;
}
scrollToSection(currentSection);
event.preventDefault(); // 阻止默认滚动,确保精准控制
}
function scrollToSection(index) {
const target = sections[index];
window.scrollTo({
top: target.offsetTop,
behavior: 'smooth'
});
}
// 添加事件监听(含 passive: false 以支持 preventDefault)
document.addEventListener('wheel', handleWheel, { passive: false });
// 【可选】增强体验:键盘方向键支持
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown' && currentSection < totalSections - 1) {
currentSection++;
scrollToSection(currentSection);
} else if (e.key === 'ArrowUp' && currentSection > 0) {
currentSection--;
scrollToSection(currentSection);
}
});
</script>
</body>
</html>⚠️ 注意事项与优化建议
- overflow: hidden 在 body 上是必需的:防止原生滚动干扰 JS 控制逻辑;
- 务必设置 passive: false:否则 event.preventDefault() 在 wheel 中无效(尤其在 Chrome/Firefox 中);
- 移动端适配:本方案默认不支持触摸拖拽滚动;如需支持,建议结合 touchstart/touchmove + scrollTop 计算,或改用 CSS scroll-snap-type: y mandatory(更轻量但兼容性略低);
- 性能提示:offsetTop 在首次调用时会触发重排,若 section 数量极多(>10),可预先缓存各 section 的 offsetTop 值;
- 无障碍考虑:保留键盘导航(已内置 ArrowUp/ArrowDown 支持),并确保每个 section 有语义化标签(如 <section> 替代 <div> 更佳)。
该方案简洁可靠,已在桌面端(含 MacBook 触控板、Magic Mouse)及主流浏览器中验证通过,是构建产品型单页导航、作品集展示或引导页的理想基础实现。


















