我有一个网站,其中的模态框通过 React Portal 运行,它们运行良好,由一个流行的库提供支持。然而,在一个地方,由于各种合理的原因,我们有一个自定义模态框,它不在门户内,也不是由库支持的。
为了方便使用,我尝试将模态框本身设置为 role="modal" 和 aria-modal="true",以提示屏幕阅读器应忽略背景。但是,背景并没有被忽略。 此网站提到有时确实需要在背景上使用 aria-hidden。在检查 React Portal 和库如何执行此操作时,它会向正文添加 aria-hidden 属性。所以我想我会试一试。
但是,当我创建一个 useEffect 来执行此操作并调用时document.body.setAttribute('aria-hidden', 'true')
,它只是忽略了我。我知道代码可以工作,我可以设置其他属性,但不能设置这个属性。你们有人知道为什么会这样吗?
编辑:关于我为什么要这样做的澄清,这是来自的 HTML 树react-modal
,我们使用的我上面提到的库,每周下载量为 170 万次:
我很想知道他们为什么这么做,尤其是当模态框是被隐藏的主体的子项时。正如其中一条评论指出的那样,这违反了 Aria 指南,似乎不应该起作用,很奇怪,但实际上确实有效。
当我在代码片段中尝试这个时:
...我在 Chrome 控制台中收到以下错误:
话虽如此,我随后确实看到该
aria-hidden="true"
属性已被添加到正文中,因此那里可能发生了一些奇怪的事情,也许与<body/>
存在有关<iframe/>
。无论如何,警告是绝对正确的——您在页面上抛出的模式包含在文档元素中
<body/>
,因此将aria-hidden="true"
隐藏<body/>
其所有内容,包括您的模式。 因此,这显然不是推荐的方法。您利用ARIA 创作实践指南模式页面并查看他们如何推荐创作模式的做法是正确的;作为编写规范的人,他们可能拥有最佳、最惯用且得到良好支持的方法。但是,我要指出的是,您所指的他们指出“有时您确实需要在后台隐藏 aria-hidden”的部分有一些重要的注意事项:
aria-hidden
设置为的任何元素的后代true
”。请永远不要将aria-hidden=true 放入正文中。
aria-hidden 有两大典型用例类别:
aria-hidden 的含义
从技术上讲,aria-hidden 会告诉浏览器从可访问性树中删除该元素,如控制台警告所示。可访问性树是提供给屏幕阅读器和其他辅助工具的结构,以便它们可以向用户呈现内容。实际上,最后,如果可访问性树中缺少某些内容,则意味着屏幕阅读器用户和使用其他辅助工具的用户将“看不到”它。它只是缺少了。
如果将 aria-hidden=true 添加到正文中,则意味着您将从可访问性树中删除所有内容,或者换句话说,您将使整个页面绝对无法访问。在 2025 年,这样做没有任何正当理由。这是不可接受的。
理想情况下,您应该尽最大努力让您的网站易于访问。但即使您不知道如何操作、不确定、害怕做错或不想做错(不幸的是,这种情况非常常见),您也不能这样断然停止。也许您的网站不太易于访问,但使用屏幕阅读器可能仍然可以在一定程度上使用它。无论如何,做点什么,哪怕是一点点,也总比什么都没有好。
aria-hidden 一去不复返。它彻底消失了,永远消失了。
aria-hidden 的正确用法
隐藏对屏幕阅读器和其他辅助工具完全无用的小元素
一般来说,aria-hidden 不应该用于页面的重要部分,例如整个对话框或整个文本段落。它应该保留用于非常小的东西,对于屏幕阅读器用户和其他辅助工具来说绝对毫无用处。
例如,一个典型的良好用法是当元素具有另一个文本标签时,隐藏按钮或其他交互元素的文本图标。
在这个例子中,图标对于屏幕阅读器用户来说完全没用,因为他们不需要知道图标在那里。如果没有 aria-hidden,屏幕阅读器可能会说一些不相关的东西,比如“无法发音的字符”、空行或任何无意义的东西。最好隐藏它。在这种情况下忘记 aria-hidden 也会给语音控制用户带来麻烦。为了激活按钮,他们可能需要阅读按钮的文本标签“推我”,以及图标的确切名称(如果它有实际名称)。
隐藏页面上暂时无效或无法访问的部分
aria-hidden 的另一个典型好用途是暂时隐藏无法访问的元素。这里的关键字是temporary unreachable。
对于对话框来说,这意味着,当对话框处于活动状态时,将 aria-hidden 放在对话框之外的所有内容上。然后当对话框变为非活动状态时,不要忘记删除 aria-hidden。
但是,你必须要聪明一点:aria-hidden=true 内的所有内容都会从可访问性树中删除。因此,如果你将 aria-hidden 放在整个主体上,你的对话框就会被隐藏,并且也无法访问!
最简单的方法是采用如下结构:
当对话框打开时,您只需将 aria-hidden=true 设置为
<main>
,当对话框关闭时,将其移除即可。除此之外,您还必须确保焦点停留在对话框内的元素上。您必须将 tabindex=-1 设置为对话框外的所有可聚焦元素,或者设置焦点陷阱。当然,不要忘记在对话框关闭时移除所有这些元素。