如何在TypeScript React的Material UI AppBar中居中标题于菜单上方
如何让MUI AppBar标题位于菜单选项上方?
当前我的AppBar中标题与菜单为横向排列,需要调整为标题在菜单选项上方的垂直布局。
以下是现有代码:
import * as React from 'react'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import Menu from '@mui/material/Menu'; import Container from '@mui/material/Container'; import Button from '@mui/material/Button'; import MenuItem from '@mui/material/MenuItem'; import {Link} from "react-router-dom"; const pages = ['Home', 'About']; function ResponsiveAppBar() { const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null); const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => { setAnchorElNav(event.currentTarget); }; const handleCloseNavMenu = () => { setAnchorElNav(null); }; return ( <AppBar position="static" sx={{ background: '#FEC107', display: "flex", flexDirection: "column", justifyContent: "center"}}> <Container maxWidth="xl"> <Toolbar disableGutters sx={{ alignItems: "flex-start", justifyContent: "center", height: "100%"}}> <Box sx={{ display: 'flex', justifyContent: 'center', flexGrow: 1 }}> <Typography variant="h6" noWrap> To Do List </Typography> <Menu id="menu-appbar" anchorEl={anchorElNav} anchorOrigin={{ vertical: 'bottom', horizontal: 'left', }} keepMounted transformOrigin={{ vertical: 'top', horizontal: 'left', }} open={Boolean(anchorElNav)} onClose={handleCloseNavMenu} sx={{ display: { xs: 'block', md: 'none' }, }} > {pages.map((page) => ( <MenuItem key={page} onClick={handleCloseNavMenu}> <Typography textAlign="center"> <Link to={`/${page}`} style={{ color: 'white' }}>{page}</Link> </Typography> </MenuItem> ))} </Menu> </Box> <Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}> {pages.map((page) => ( <Button key={page} onClick={handleCloseNavMenu} sx={{ my: 2, color: 'white', display: 'block' }} > <Link to={`/${page}`} style={{ color: 'black', fontWeight: 'bold', textDecoration: 'none' }}>{page}</Link> </Button> ))} </Box> </Toolbar> </Container> </AppBar> ); } export default ResponsiveAppBar;
解决方案
核心是调整Toolbar和内部容器的flex布局方向,实现标题与菜单的垂直排列:
- 修改
Toolbar的布局为垂直方向,并居中对齐元素 - 调整标题区域和菜单区域的间距与布局属性
修改后的完整代码:
import * as React from 'react'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import Menu from '@mui/material/Menu'; import Container from '@mui/material/Container'; import Button from '@mui/material/Button'; import MenuItem from '@mui/material/MenuItem'; import {Link} from "react-router-dom"; import MenuIcon from '@mui/icons-material/Menu'; import IconButton from '@mui/material/IconButton'; const pages = ['Home', 'About']; function ResponsiveAppBar() { const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null); const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => { setAnchorElNav(event.currentTarget); }; const handleCloseNavMenu = () => { setAnchorElNav(null); }; return ( <AppBar position="static" sx={{ background: '#FEC107' }}> <Container maxWidth="xl"> <Toolbar disableGutters sx={{ flexDirection: 'column', alignItems: 'center', py: 2 }}> {/* 标题与移动端菜单触发按钮 */} <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', mb: 1 }}> <Typography variant="h6" noWrap> To Do List </Typography> {/* 补充移动端菜单触发按钮 */} <IconButton size="large" aria-controls="menu-appbar" aria-haspopup="true" onClick={handleOpenNavMenu} color="inherit" sx={{ ml: 2, display: { xs: 'block', md: 'none' } }} > <MenuIcon /> </IconButton> <Menu id="menu-appbar" anchorEl={anchorElNav} anchorOrigin={{ vertical: 'bottom', horizontal: 'center', }} keepMounted transformOrigin={{ vertical: 'top', horizontal: 'center', }} open={Boolean(anchorElNav)} onClose={handleCloseNavMenu} sx={{ display: { xs: 'block', md: 'none' }, }} > {pages.map((page) => ( <MenuItem key={page} onClick={handleCloseNavMenu}> <Typography textAlign="center"> <Link to={`/${page}`} style={{ color: 'black', textDecoration: 'none' }}>{page}</Link> </Typography> </MenuItem> ))} </Menu> </Box> {/* 桌面端菜单 */} <Box sx={{ display: { xs: 'none', md: 'flex' }, gap: 3 }}> {pages.map((page) => ( <Button key={page} onClick={handleCloseNavMenu} sx={{ color: 'black', fontWeight: 'bold' }} > <Link to={`/${page}`} style={{ color: 'inherit', textDecoration: 'none' }}>{page}</Link> </Button> ))} </Box> </Toolbar> </Container> </AppBar> ); } export default ResponsiveAppBar;
关键修改说明
- 将
Toolbar的flexDirection设为column,强制内部元素垂直排列 - 给标题区域添加
mb:1,让标题与菜单之间保留合理间距 - 桌面端菜单使用
gap:3控制按钮间距,替代原有的my:2 - 补充了移动端菜单的触发按钮(原代码缺失,否则移动端菜单无法打开)
- 调整移动端菜单的锚点位置,使其从标题下方居中弹出
内容的提问来源于stack exchange,提问作者Jessica Huyser
相关产品推荐
相关产品推荐

