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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 19:30:53