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

MUI 5菜单下拉框显示在页面左侧而非按钮下方问题求助

MUI 5 下拉菜单定位错误解决方法

问题原因

你将IconButton嵌套在Button内部,点击事件绑定在外层Button上,导致菜单的锚点元素是Button而非头像按钮,再加上默认的菜单定位规则,就出现了菜单跑到页面左侧的情况。外层Button的结构也干扰了MUI对锚点位置的计算。

解决方法

方案一:简化结构,绑定点击事件到头像按钮

直接把点击事件绑定到包含Avatar的IconButton上,移除不必要的外层Button,同时显式设置菜单的定位属性:

import { useState } from 'react';
import { Stack, IconButton, Avatar, Menu, MenuItem, KeyboardArrowDownIcon } from '@mui/material';

export default function ProfileMenu() {
  const [anchorEl, setAnchorEl] = useState(null);
  const open = Boolean(anchorEl);
  
  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };
  
  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <Stack direction="row" alignItems="center" spacing={{ xs: 0.5, sm: 1.5 }} sx={{ color: "black" }}>
      <IconButton
        onClick={handleClick}
        sx={{ border: `1px solid ${theme.palette.primary.neutral400}`, borderRadius: "16px", marginRight: "8px" }}
        id="basic-button"
        aria-controls={open ? "basic-menu" : undefined}
        aria-haspopup="true"
        aria-expanded={open ? "true" : undefined}
      >
        <Avatar alt="Profile" src={ProfilePicture} />
        <KeyboardArrowDownIcon />
      </IconButton>
      <Menu
        id="basic-menu"
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        // 显式设置菜单相对于锚点的位置
        anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
        transformOrigin={{ vertical: 'top', horizontal: 'right' }}
        MenuListProps={{
          "aria-labelledby": "basic-button",
        }}
      >
        <MenuItem onClick={handleClose}>个人资料</MenuItem>
        <MenuItem onClick={handleClose}>我的账户</MenuItem>
        <MenuItem onClick={handleClose}>退出登录</MenuItem>
      </Menu>
    </Stack>
  );
}

方案二:保留外层Button,修正定位

如果需要保留外层Button,要确保Button的布局正确,并显式设置菜单定位:

import { useState } from 'react';
import { Stack, Button, IconButton, Avatar, Menu, MenuItem, KeyboardArrowDownIcon } from '@mui/material';

export default function ProfileMenu() {
  const [anchorEl, setAnchorEl] = useState(null);
  const open = Boolean(anchorEl);
  
  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };
  
  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <Stack direction="row" alignItems="center" spacing={{ xs: 0.5, sm: 1.5 }} sx={{ color: "black" }}>
      <Button
        onClick={handleClick}
        endIcon={<KeyboardArrowDownIcon />}
        id="basic-button"
        aria-controls={open ? "basic-menu" : undefined}
        aria-haspopup="true"
        aria-expanded={open ? "true" : undefined}
        sx={{ color: "black", display: 'flex', alignItems: 'center' }}
      >
        <IconButton sx={{ border: `1px solid ${theme.palette.primary.neutral400}`, borderRadius: "16px", marginRight: "8px" }}>
          <Avatar alt="Profile" src={ProfilePicture} />
        </IconButton>
      </Button>
      <Menu
        id="basic-menu"
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
        transformOrigin={{ vertical: 'top', horizontal: 'right' }}
        MenuListProps={{
          "aria-labelledby": "basic-button",
        }}
      >
        <MenuItem onClick={handleClose}>个人资料</MenuItem>
        <MenuItem onClick={handleClose}>我的账户</MenuItem>
        <MenuItem onClick={handleClose}>退出登录</MenuItem>
      </Menu>
    </Stack>
  );
}

关键要点

  • 锚点元素正确:菜单的anchorEl必须是点击触发的元素,这样MUI才能准确计算菜单位置。
  • 显式定位属性:通过anchorOrigin和transformOrigin可以精确控制菜单的展开位置,anchorOrigin定义菜单相对于锚点的位置,transformOrigin定义菜单自身的展开原点。

内容的提问来源于stack exchange,提问作者Rahil Əliyev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:10:49