从dialog内触发Snackbars无法被屏幕阅读器读取问题咨询
问题原因
Dialog默认开启模态模式时,会给自身以外的所有DOM节点添加aria-hidden="true"标记,而Snackbar组件默认挂载在页面body根节点下,属于Dialog外部元素,因此会被屏幕阅读器判定为不可访问内容,即使内容展示在视觉上层也不会被播报。
解决方案
这里以常用的Material UI组件库为例,其他组件库逻辑通用:
方案1(推荐):修改Snackbar挂载容器
将Snackbar的挂载节点指定为Dialog内部的DOM元素,避免被Dialog的模态隐藏规则覆盖,是兼容性最好的解法。
示例代码:
import { useState, useRef } from 'react'; import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import Button from '@mui/material/Button'; import Snackbar from '@mui/material/Snackbar'; export default function Demo() { // 存储Dialog内部节点的ref const dialogInnerRef = useRef(null); const [dialogOpen, setDialogOpen] = useState(false); const [snackbarOpen, setSnackbarOpen] = useState(false); return ( <> <Button onClick={() => setDialogOpen(true)}>OPEN DIALOG</Button> <Dialog open={dialogOpen} onClose={() => setDialogOpen(false)}> <DialogContent ref={dialogInnerRef}> <Button onClick={() => setSnackbarOpen(true)}>OPEN SNACKBAR</Button> </DialogContent> </Dialog> <Snackbar open={snackbarOpen} autoHideDuration={5000} onClose={() => setSnackbarOpen(false)} message="操作成功" // 核心配置:指定挂载到Dialog内部节点 container={dialogInnerRef.current} // 额外增强可访问性,确保阅读器优先播报 aria-live="assertive" role="alert" /> </> ); }
方案2:关闭Dialog的模态强制隐藏规则
如果不方便修改Snackbar挂载节点,可以给Dialog添加disablePortal={true}和aria-modal="false"配置,关闭Dialog对外部元素的隐藏标记,不过该方案可能会影响Dialog本身的可访问性表现,仅作为备选。
注意事项
如果将Snackbar挂载到Dialog内部后出现被裁剪的问题,可给DialogContent添加样式overflow: visible即可解决。
内容的提问来源于stack exchange,提问作者user1569333
相关产品推荐
相关产品推荐

