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

使用MUI Menu添加HTML元素时布局出现异常滚动跳转问题

解决MUI Menu关闭时页面滚动跳转的问题

问题根源

关闭Menu时,MUI默认会将焦点恢复到触发它的按钮(restoreFocus默认值为true)。而你在Menu打开后给按钮上方添加了div,导致按钮的页面位置发生变化,浏览器会自动滚动到获得焦点的按钮,从而出现大幅跳转。

解决方案

1. 禁用Menu的焦点恢复行为

直接设置Menu的restoreFocus属性为false,阻止关闭时将焦点返回按钮,从根源避免浏览器自动滚动:

import { useState } from 'react';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import Button from '@mui/material/Button';

export default function App() {
  const [anchorEl, setAnchorEl] = useState(null);
  const open = Boolean(anchorEl);
  const [hasDiv, setHasDiv] = useState(false);

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const addDiv = () => {
    setHasDiv(true);
  };

  return (
    <div>
      {hasDiv && <div style={{ height: '200px', backgroundColor: '#eee' }}>新增的div</div>}
      <Button 
        id="basic-button"
        aria-controls={open ? 'basic-menu' : undefined}
        aria-haspopup="true"
        aria-expanded={open ? 'true' : undefined}
        onClick={handleClick}
        style={{ marginTop: '500px' }}
      >
        打开菜单
      </Button>
      <Menu
        id="basic-menu"
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        restoreFocus={false} // 关键:禁用焦点恢复
      >
        <MenuItem onClick={addDiv}>添加上方div</MenuItem>
        <MenuItem onClick={handleClose}>关闭</MenuItem>
      </Menu>
    </div>
  );
}

2. 若需保留焦点恢复,手动控制滚动位置

如果你需要关闭Menu后焦点回到按钮,可在关闭时记录当前滚动位置,恢复焦点后强制保持原位置:

const handleClose = () => {
  // 记录关闭前的滚动位置
  const scrollPos = window.pageYOffset || document.documentElement.scrollTop;
  setAnchorEl(null);
  // 下一帧恢复滚动位置,覆盖浏览器自动滚动行为
  requestAnimationFrame(() => {
    window.scrollTo(0, scrollPos);
  });
};

3. 禁用Menu打开时的自动滚动(可选)

如果连Menu打开时的自动滚动都不需要,可通过PopperProps修改Popper的行为,关闭自动滚动到锚点的逻辑:

<Menu
  // 其他属性
  PopperProps={{
    modifiers: [
      {
        name: 'preventOverflow',
        options: {
          enabled: false, // 关闭自动滚动调整
        },
      },
    ],
  }}
>
  {/* 菜单项 */}
</Menu>

验证效果

测试时,先滚动页面让按钮部分移出屏幕,打开Menu并添加上方div,关闭Menu后页面不会再出现大幅滚动跳转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:52:53