
本文介绍如何通过原生 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' }) 实现平滑跳转。
? 完整代码示例
<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><div class="container">
<div class="sections" id="sectionOne"><p>DIV 1</p></div>
<div class="sections" id="sectionTwo"><p>DIV 2</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/js/7987" title="HTML5文章图片滚动视差显示特效"><img
src="https://img.php.cn/upload/jscode/000/000/011/170901570356743.jpg" alt="HTML5文章图片滚动视差显示特效" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/js/7987" title="HTML5文章图片滚动视差显示特效" class="overflowclass">HTML5文章图片滚动视差显示特效</a>
<p class="overflowclass">HTML5文章图片滚动视差显示特效是一款在文章中加入图片,滚动的时候会显示视差效果,会增强读者的阅读体验。</p>
</div>
<a rel="nofollow" href="/xiazai/js/7987" title="HTML5文章图片滚动视差显示特效" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div></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>
⚠️ 注意事项与优化建议
- 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 有语义化标签(如
替代 更佳)。该方案简洁可靠,已在桌面端(含 MacBook 触控板、Magic Mouse)及主流浏览器中验证通过,是构建产品型单页导航、作品集展示或引导页的理想基础实现。










