You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Overlay菜单打开时隐藏主滚动条并锁定Body滚动,关闭时恢复

Hey there! This is a super common requirement for overlays, and I’ve got a straightforward, robust solution that works across most modern browsers. Let me break it down for you:

Lock Body Scroll When Overlay is Open (Restore on Close)

Step 1: Handle the Overlay Open State

When your overlay switches to the "open" state, you need two key actions to lock the main page:

  • Hide the main scrollbar and prevent layout shift
  • Block scroll events from affecting the body behind the overlay

Here’s the JavaScript code to implement this:

// Store original body styles first so we can revert them later
const originalBodyStyles = {
  overflow: document.body.style.overflow,
  paddingRight: document.body.style.paddingRight
};

function openOverlay() {
  // Calculate the width of the browser's scrollbar
  const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
  
  // Lock body scroll and add padding to avoid layout shift
  document.body.style.overflow = 'hidden';
  document.body.style.paddingRight = `${scrollbarWidth}px`;
  
  // Prevent scroll inside the overlay from affecting the body
  const overlay = document.getElementById('your-overlay-element-id');
  overlay.addEventListener('wheel', (e) => e.stopPropagation());
  overlay.addEventListener('touchmove', (e) => e.stopPropagation());
}

Step 2: Restore Scroll When Closing the Overlay

When you close the overlay, just revert the body back to its original state and clean up event listeners:

function closeOverlay() {
  // Restore original body styles
  document.body.style.overflow = originalBodyStyles.overflow;
  document.body.style.paddingRight = originalBodyStyles.paddingRight;
  
  // Remove scroll propagation listeners from the overlay
  const overlay = document.getElementById('your-overlay-element-id');
  overlay.removeEventListener('wheel', (e) => e.stopPropagation());
  overlay.removeEventListener('touchmove', (e) => e.stopPropagation());
}

Bonus: CSS-First Approach (If You Prefer)

If you like keeping styles in CSS, you can use a class-based method instead:
First define the CSS class:

.body-scroll-locked {
  overflow: hidden;
  /* Use a CSS variable to handle scrollbar width dynamically */
  padding-right: var(--scrollbar-width, 0);
}

Then toggle the class with JavaScript:

function openOverlay() {
  const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
  document.documentElement.style.setProperty('--scrollbar-width', `${scrollbarWidth}px`);
  document.body.classList.add('body-scroll-locked');
  
  // Add overlay scroll block listeners here too, same as above
}

function closeOverlay() {
  document.body.classList.remove('body-scroll-locked');
  document.documentElement.style.removeProperty('--scrollbar-width');
  
  // Remove overlay scroll block listeners here
}

Why This Works

  • overflow: hidden on the body completely stops the main page from scrolling
  • The padding-right fix prevents the page content from shifting left when the scrollbar disappears
  • Stopping scroll event propagation ensures that scrolling inside the overlay stays contained there

This solution works on desktop, mobile, and all major modern browsers. If you run into edge cases (like custom scrollbars), let me know and we can tweak it further!

内容的提问来源于stack exchange,提问作者Vizzale

火山引擎 最新活动