Modal对话框关闭后页面滚动条消失怎么办?

Dev · 玉轩 阅读 37

我在用React写一个Modal组件,弹出时body加了overflow:hidden防止背景滚动,但关闭Modal后页面的滚动条就没了,内容还向左偏移了一点,看起来特别别扭。

我试过在useEffect里加回overflow: auto,但有时候还是不生效,尤其是在快速打开关闭的时候。有没有靠谱的处理方式?

useEffect(() => {
  if (isOpen) {
    document.body.style.overflow = 'hidden';
  } else {
    document.body.style.overflow = 'auto';
  }
}, [isOpen]);
我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
长孙义霞
这问题我碰到过,典型的滚动条闪退问题。根本原因是直接修改body的style会导致滚动条宽度突然变化,引起布局抖动。

更稳的做法是用class来控制,先记录原始overflow值,关闭时还原回去。试试这样改:

useEffect(() => {
const originalOverflow = document.body.style.overflow;

if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = originalOverflow || '';
}

return () => {
document.body.style.overflow = originalOverflow || '';
};
}, [isOpen]);


如果还有问题,可能是其他样式干扰,可以再加个padding-right补偿滚动条宽度:

const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

useEffect(() => {
if (isOpen) {
document.body.style.paddingRight = ${scrollbarWidth}px;
document.body.style.overflow = 'hidden';
} else {
document.body.style.paddingRight = '';
document.body.style.overflow = '';
}
}, [isOpen]);


这招在antd的Modal里也用到了,实测靠谱。快速开关的问题用cleanup函数就能解决,别忘了在effect里做清理。
点赞
2026-03-09 23:05
Newb.晨旭
问题在于你没保存原始值,而且快速开关时cleanup没执行完。用空字符串恢复默认值,在cleanup里处理:

useEffect(() => {
if (isOpen) {
const original = document.body.style.overflow;
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = original || '';
};
}
}, [isOpen]);


这样即使快速开关也能正确恢复,因为React保证cleanup在下一个effect前执行完。
点赞 6
2026-03-01 02:00