菜鸟科技网

如何禁止页面滚动事件?30字疑问标题,如何禁止页面滚动事件?

使用 overflow: hidden (最常用、最简单)

这是最直接、最常用的方法,通过给 body 元素设置 overflow: hidden,可以禁止整个页面的滚动条出现。

如何禁止页面滚动事件?30字疑问标题,如何禁止页面滚动事件?-图1
(图片来源网络,侵删)

如何实现?

在需要禁止滚动的时机(打开模态框时),向 body 添加一个类,no-scroll,并定义这个类的样式。

CSS 定义

.no-scroll {
  /* 禁止页面滚动 */
  overflow: hidden; 
  /* 可选:防止页面在iOS上仍能轻微滚动 */
  position: fixed; 
  /* 为了防止页面因position: fixed而跳动,需要设置一个与视口高度相等的宽度 */
  width: 100vw; 
  /* 为了防止页面因position: fixed而跳动,需要设置一个与视口高度相等的高度 */
  height: 100vh; 
}

JavaScript 操作

当需要禁止滚动时:

如何禁止页面滚动事件?30字疑问标题,如何禁止页面滚动事件?-图2
(图片来源网络,侵删)
document.body.classList.add('no-scroll');

当需要恢复滚动时:

document.body.classList.remove('no-scroll');

优点

  • 简单直接:CSS 原生属性,易于理解和实现。
  • 兼容性好:在所有现代浏览器中都表现良好。

缺点

  • 页面跳动:当 overflow: hidden 生效时,滚动条会消失,导致页面内容宽度突然增加(等于滚动条的宽度),页面会向左“跳动”一下,虽然 position: fixed; width: 100vw; height: 100vh; 可以在很大程度上缓解这个问题,但在某些复杂布局下仍可能产生细微影响。
  • 滚动位置丢失:如果用户已经滚动了一部分页面,然后禁止滚动,再恢复时,页面会“跳”回顶部,这是因为 position: fixed 会将元素相对于视口定位,脱离了正常的文档流。

使用 preventDefault() (更精细的控制)

通过监听 touchmovewheel 事件,并在事件处理函数中调用 event.preventDefault(),可以阻止事件的默认行为,从而阻止滚动。

如何实现?

禁止滚动

// 禁用鼠标滚轮
function preventScroll(e) {
  e.preventDefault();
}
// 禁用触摸移动(移动端)
function preventTouchMove(e) {
  e.preventDefault();
}
// 添加事件监听
document.addEventListener('wheel', preventScroll, { passive: false });
document.addEventListener('touchmove', preventTouchMove, { passive: false });
// body的样式可以不加,但加上可以防止页面跳动
document.body.style.overflow = 'hidden';

恢复滚动

// 移除事件监听
document.removeEventListener('wheel', preventScroll);
document.removeEventListener('touchmove', preventTouchMove);
// 恢复body的样式
document.body.style.overflow = '';

重要提示:{ passive: false } 在调用 addEventListener 时,必须设置 passive: false,这是因为现代浏览器为了提升滚动性能,默认将 touchmovewheel 事件监听器设为 passive: true,这意味着你不能在事件处理函数中调用 preventDefault(),浏览器会忽略它并抛出警告。passive: false 告诉浏览器:“我可能会调用 preventDefault(),请先等待,不要优化滚动”。

优点

  • 无页面跳动:因为滚动条本身还在,只是被禁用了,所以不会出现宽度变化导致的跳动。
  • 保留滚动位置:恢复滚动时,页面会停留在之前的位置。

缺点

  • 实现稍复杂:需要手动添加和移除事件监听器。
  • 可能影响性能preventDefault 的处理逻辑复杂,可能会对滚动性能产生轻微影响(尽管通常不明显)。

结合 position: fixedscrollTop (解决位置丢失问题)

这是对方法一的优化,完美解决了“页面跳动”和“滚动位置丢失”两个问题。

原理

  1. 在禁止滚动前,记录当前页面的滚动位置 (scrollTop)。
  2. body 设置 position: fixedtop 值(值为负的滚动位置),这会把整个页面“钉”在当前位置,即使没有滚动条,视觉上也不会跳动。
  3. 当恢复滚动时,移除 position: fixed,并将页面滚动回之前记录的位置。

如何实现?

// 存储滚动位置的变量
let scrollPosition = 0;
function disableScroll() {
  // 1. 记录当前滚动位置
  scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
  // 2. 给body添加样式,固定页面
  document.body.style.position = 'fixed';
  document.body.style.top = `-${scrollPosition}px`;
  document.body.style.width = '100%'; // 防止内容挤压
}
function enableScroll() {
  // 1. 移除body的固定样式
  document.body.style.position = '';
  document.body.style.top = '';
  document.body.style.width = '';
  // 2. 滚动回之前记录的位置
  window.scrollTo(0, scrollPosition);
}
// 使用示例
// 打开模态框时
disableScroll();
// 关闭模态框时
enableScroll();

优点

  • 完美解决所有问题:既没有页面跳动,也保留了滚动位置,兼容性也很好。
  • 用户体验最佳:这是目前最推荐的方案,尤其是在需要频繁开关滚动的场景下。

缺点

  • 代码量稍多:需要额外的逻辑来记录和恢复滚动位置。

总结与推荐

方法 优点 缺点 推荐场景
overflow: hidden 简单、快速 页面跳动、滚动位置丢失 简单的、一次性的弹窗,对跳动不敏感的场景。
preventDefault() 无跳动、保留位置 代码稍复杂、需注意 passive: false 需要精细控制、不能有页面跳动的场景。
position: fixed + scrollTop 无跳动、保留位置、兼容性好 代码量稍多 强烈推荐,特别是移动端、复杂页面、或需要多次开关滚动的场景。

最终建议:

对于绝大多数项目,特别是追求良好用户体验的项目,强烈推荐使用方法三 (position: fixed + scrollTop),它虽然代码多几行,但完美解决了核心痛点,是专业且健壮的解决方案。

如果你的项目非常简单,或者只是一个临时的演示,并且不介意页面跳动,那么方法一 (overflow: hidden) 也是一个快速的选择。

分享:
扫描分享到社交APP
上一篇
下一篇