如何实现滚动时直接平滑跳转至对应ID区块的功能?
实现单步平滑滚动跳转(每次滚动直接跳转到相邻区块)
我完全懂你要的效果——不管滚轮滚了多少,向下滚一次就直接滑到下一个带ID的区块,向上滚一次就回到上一个,全程平滑过渡但不会在中间停留,就像示例里那样从顶部直接跳到中间区块对吧?下面是我常用的实现方案,用jQuery就能搞定:
第一步:先搭好页面结构
首先得给每个需要跳转的区块设置唯一ID,并且让每个区块占满视口(这样效果更直观):
<div id="section1" class="section">顶部区块</div> <div id="section2" class="section">中间区块</div> <div id="section3" class="section">底部区块</div> <style> .section { height: 100vh; /* 每个区块占满屏幕高度 */ display: flex; align-items: center; justify-content: center; font-size: 2rem; } #section1 { background: #f5f5f5; } #section2 { background: #e0e0e0; } #section3 { background: #bdbdbd; } </style>
第二步:核心JS逻辑(jQuery版)
这里的关键是监听滚轮事件、判断滚动方向、锁定当前区块、平滑跳转,还要加个节流防止连续滚动触发多次:
$(document).ready(function() { // 存储所有区块的DOM元素和它们的offsetTop const sections = $('.section'); const sectionOffsets = sections.map(function() { return $(this).offset().top; }).get(); let currentSectionIndex = 0; let isScrolling = false; // 节流标记,防止滚动动画未完成时重复触发 // 监听滚轮事件 $(window).on('wheel', function(e) { if (isScrolling) return; // 动画正在进行时不响应新的滚动 isScrolling = true; // 判断滚动方向:deltaY为正是向下滚,负是向上滚 const direction = e.originalEvent.deltaY > 0 ? 'down' : 'up'; // 更新当前区块索引 if (direction === 'down' && currentSectionIndex < sections.length - 1) { currentSectionIndex++; } else if (direction === 'up' && currentSectionIndex > 0) { currentSectionIndex--; } // 平滑滚动到目标区块 $('html, body').animate({ scrollTop: sectionOffsets[currentSectionIndex] }, 800, function() { isScrolling = false; // 动画完成后解锁 }); // 阻止默认滚动行为,避免页面跟着滚轮动 e.preventDefault(); }); });
关键细节说明
- 节流标记
isScrolling:这个很重要,不然用户快速滚动的时候会触发一堆动画,导致页面跳来跳去。 deltaY判断方向:原生滚轮事件的deltaY属性可以直接判断滚动方向,比监听scrollTop变化更准确。animate的scrollTop:同时给html和body设置是为了兼容不同浏览器(比如Chrome和Firefox的滚动根元素不一样)。- 阻止默认行为:必须调用
e.preventDefault(),不然浏览器的默认滚动会和我们的自定义滚动冲突,导致页面抖动。
如果不用jQuery的话,也可以用原生JS的scrollTo方法配合behavior: 'smooth',不过兼容性稍差一点,逻辑是类似的。
内容的提问来源于stack exchange,提问作者DEDSEC _588
相关产品推荐
相关产品推荐

