You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使透明div后方的内容不可滚动/保持静态?

解决侧边栏遮罩层后方内容可滚动的问题

问题说明

开发侧边栏时,后方的深色透明遮罩层点击可隐藏侧边栏,但遮罩层透明状态下,用户仍能滚动后方页面内容,需要实现遮罩层显示时,后方内容静态不可滚动。

解决方案

方法1:锁定body全局滚动(最常用)

当侧边栏(含遮罩层)显示时,给body添加样式类锁定滚动,隐藏时移除该类。

修改后的组件代码:

import { useEffect, useState } from 'react';

export default function Sidebar() {
    const [isOpen, setIsOpen] = useState(true); // 根据业务逻辑控制侧边栏显隐

    // 监听侧边栏状态,控制body滚动
    useEffect(() => {
        const body = document.body;
        if (isOpen) {
            body.classList.add('no-scroll');
        } else {
            body.classList.remove('no-scroll');
        }
        // 组件卸载时清理样式,避免影响其他页面
        return () => body.classList.remove('no-scroll');
    }, [isOpen]);

    // 点击遮罩层关闭侧边栏
    const closeSidebar = () => setIsOpen(false);

    return (
        {/* 外层遮罩层,覆盖整个视口 */}
        <div className={`sidebar-overlay ${isOpen ? 'active' : ''}`} onClick={closeSidebar}>
            {/* 侧边栏容器,点击内部阻止事件冒泡,避免触发遮罩层的关闭逻辑 */}
            <div className="sidebar-container" onClick={e => e.stopPropagation()}>
                <div className="sidebar">
                    <header>header</header>
                    <ul>
                        <li>
                            <div className="sidebar-item">item</div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    );
}

对应的CSS样式:

/* 遮罩层基础样式 */
.sidebar-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5); /* 深色透明效果 */
    display: none; /* 默认隐藏 */
}

/* 遮罩层激活状态 */
.sidebar-overlay.active {
    display: block;
}

/* 锁定body滚动的类 */
.no-scroll {
    overflow: hidden;
    /* 兼容iOS滚动问题,可选 */
    position: fixed;
    width: 100%;
}

/* 侧边栏容器样式示例 */
.sidebar-container {
    position: fixed;
    right: 0;
    top: 0;
    height: 100vh;
    width: 300px;
    background-color: #fff;
    /* 可添加其他样式如阴影、内边距等 */
}

方法2:遮罩层阻止滚动事件传递

如果不需要锁定整个页面滚动,可在遮罩层上监听滚动相关事件,阻止事件传递到后方内容。

修改后的组件代码:

import { useState } from 'react';

export default function Sidebar() {
    const [isOpen, setIsOpen] = useState(true);

    const closeSidebar = () => setIsOpen(false);
    // 阻止滚动事件
    const preventScroll = e => e.preventDefault();

    return (
        <div 
            className={`sidebar-overlay ${isOpen ? 'active' : ''}`} 
            onClick={closeSidebar}
            onWheel={preventScroll}
            onTouchMove={preventScroll}
        >
            <div className="sidebar-container" onClick={e => e.stopPropagation()}>
                <div className="sidebar">
                    <header>header</header>
                    <ul>
                        <li>
                            <div className="sidebar-item">item</div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    );
}

对应的CSS样式:

.sidebar-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    display: none;
    pointer-events: auto; /* 确保遮罩层能接收事件 */
}

.sidebar-overlay.active {
    display: block;
}

.sidebar-container {
    position: fixed;
    right: 0;
    top: 0;
    height: 100vh;
    width: 300px;
    background-color: #fff;
}

关键注意事项

  • 方法1是行业通用方案,能彻底解决滚动问题,但必须在组件卸载时清理no-scroll类,避免影响其他页面的正常滚动。
  • 方法2适合局部场景,但要同时处理鼠标滚轮(wheel)和移动端触摸滚动(touchmove)事件,确保兼容性。
  • 遮罩层必须是外层容器,侧边栏内部点击通过stopPropagation()阻止事件冒泡,避免误触关闭逻辑。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 18:16:05