如何为Material-UI Snackbar的anchorOrigin添加vertical:center值实现垂直居中
实现Material-UI Snackbar垂直居中的原生式方案
Material-UI的Snackbar组件默认仅支持top/bottom两种垂直锚点,但可以通过自定义样式覆盖的方式,让anchorOrigin的vertical字段支持自定义的center值,无需依赖height:100%的临时方案。
方案一:组件内直接处理样式(快速实现)
修改你的Toast组件,根据anchorOrigin.vertical的值动态生成居中样式,同时移除冗余的height属性:
export default function Toast() { const toast = useSelector((state) => state.toast); const dispatch = useDispatch(); const handleClose = (_, reason) => { if (reason === 'clickaway') { return; } dispatch(toggleToast({ open: false })); }; // 根据垂直锚点生成对应样式 const snackbarSx = () => { const targetVertical = toast.position?.vertical || 'top'; if (targetVertical === 'center') { return { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', // 覆盖默认的top/bottom定位逻辑 top: 'auto', bottom: 'auto' }; } return {}; }; return ( <Snackbar sx={snackbarSx()} open={true} anchorOrigin={toast.position ? toast.position : { vertical: 'top', horizontal: 'center' }} autoHideDuration={toast.duration === undefined ? 4500 : toast.duration} onClose={handleClose} > <Alert variant="filled" severity={toast.severity}> {toast.message} </Alert> </Snackbar> ); }
调用时直接传递vertical: "center",无需再传height字段:
dispatch( toggleToast({ message: "Saved successfully", severity: "success", position: { vertical: "center", horizontal: "center" } }) )
方案二:全局主题扩展(优雅复用)
如果项目中多个地方需要使用居中的Snackbar,推荐通过自定义Material-UI主题实现全局样式覆盖,让所有Snackbar自动识别vertical: "center":
1. 创建自定义主题
import { createTheme, ThemeProvider } from '@mui/material/styles'; const customTheme = createTheme({ components: { MuiSnackbar: { styleOverrides: { root: ({ ownerState }) => { const { anchorOrigin } = ownerState; // 当锚点垂直方向为center时应用居中样式 if (anchorOrigin?.vertical === 'center') { return { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', top: 'auto', bottom: 'auto' }; } return {}; } } } } });
2. 在项目根节点注入主题
function App() { return ( <ThemeProvider theme={customTheme}> {/* 你的应用内容 */} </ThemeProvider> ); }
3. 使用方式
此时你的Toast组件无需额外处理样式,直接使用vertical: "center"即可:
// Toast组件保持原结构,移除sx中的height属性 export default function Toast() { const toast = useSelector((state) => state.toast); const dispatch = useDispatch(); const handleClose = (_, reason) => { if (reason === 'clickaway') { return; } dispatch(toggleToast({ open: false })); }; return ( <Snackbar open={true} anchorOrigin={toast.position ? toast.position : { vertical: 'top', horizontal: 'center' }} autoHideDuration={toast.duration === undefined ? 4500 : toast.duration} onClose={handleClose} > <Alert variant="filled" severity={toast.severity}> {toast.message} </Alert> </Snackbar> ); }
调用时同样只需传递vertical: "center":
dispatch( toggleToast({ message: "Saved successfully", severity: "success", position: { vertical: "center", horizontal: "center" } }) )
方案说明
这两种方案都是通过覆盖Snackbar的定位样式实现垂直居中,本质是利用CSS的transform: translate(-50%, -50%)实现精准居中,比设置height:100%的方式更符合组件的定位逻辑,也避免了冗余的布局属性。
内容的提问来源于stack exchange,提问作者Yerzhan
相关产品推荐
相关产品推荐

