“咏叹调隐藏元素不包含可聚焦元素"显示模态时的问题 [英] "aria-hidden elements do not contain focusable elements" issue when modal is shown
问题描述
我在我的应用程序中使用 React Modal,当它打开时运行 aXe 辅助工具 给出以下错误:
这是因为 React modal 添加了 aria-hidden="true"
到应用程序的根元素(我的所有应用程序组件都在 div 下呈现,但不是 modal),但它不会更新标签索引或禁用每个可聚焦元素.
然而,React 模态会捕获键盘焦点,因此用户无法退出模态并单击背景关闭模态.
所以我的问题是:
这真的是我需要解决的问题吗?或者这是一个误报,因为该工具不了解模态捕获焦点?
如果确实需要修复此问题,我是否只能选择手动更新选项卡索引或禁用每个可聚焦元素?
谢谢!
模式打开时的 HTML 看起来像这样:
简答
将 aria-modal
添加到您的模态将消除此警告.
长答案
我花了一段时间才意识到为什么我们的模态没有这个警告,但你的会有,因为我们使用了类似的标记.我们在模态上使用 aria-modal
属性.
Axe 已更新为在模态上使用 aria-modal
属性.aria-modal
目前有 一般支持,但它是一种很好的做法,因为它可以解决开发人员的错误(因为尊重它的屏幕阅读器/浏览器组合会自动为您捕获焦点!).
在模态之外隐藏项目
真正隐藏所有内容的唯一方法是将 tabindex="-1"
添加到每个交互式项目中.
但实际上,如果您用于将 tabindex=-1"
添加到每个交互式元素的 JS 函数遇到问题并且没有遇到问题,那么这更有可能导致灾难性的可访问性问题成功还原 tabindex
或将其删除.这意味着您将完全无法访问页面的某些部分!
很明显,你会在Robust"上通过 WCAG 失败.POUR 的一部分.请不要这样做.
最好的折衷方案是在 和
容器(任何顶级容器)上使用
aria-hidden
).然后在您的模态上使用 aria-modal
,因为这会在某些浏览器/屏幕阅读器组合中捕获焦点.aria
的这种组合将为浏览器支持提供最高的覆盖范围.
最后,您应该使用 tab
键管理人们的焦点.这是我们在上述方法失败的情况下以及不使用屏幕阅读器的人(即无法使用鼠标的灵巧性或准确性问题的人)的备份.
如果您需要有关如何在模态中捕获选项卡焦点的信息,我将提供一个代码示例,但它非常简单.
管理 Tab 键焦点不会阻止屏幕阅读器用户或行为不端的插件超出您的模式(如果其他方法失败)但相信我,如果他们在您实施后对您的网站有问题以上他们会在其他网站上有更大的问题.
inert - 你的弓的另一根弦?
最后作为另一个备份,我们添加 inert
到我们模态之外的项目.支持不是很好,但每一点都有帮助!
如果你愿意,你可以对它进行 polyfill,但我认为它还没有超出草案规范,所以我们只是按原样使用它.
它纯粹是另一个附加组件,并且(希望)可以证明我们的遗留应用程序的未来,因为 inert
是一个非常需要且易于理解的属性.它在不改变视觉设计的情况下阻止屏幕阅读器访问项目(基本上是 aria-hidden
,但作为标准属性,其优点是它可以有效地从无障碍树中删除所有子项.)
示例
尝试从以下示例中删除 aria-modal="true"
并运行 Axe,警告将返回.
<main aria-hidden="true" inert><a href="https://google.com">test<;/a></main><div class="modal" aria-hidden="false" aria-modal="true"><label for="iTest">输入测试</label><input id="iTest"/>
I'm using React Modal in my application and when it is open running the aXe accessibility tool gives the following error:
aria-hidden elements do not contain focusable elements
This is because the React modal adds a aria-hidden="true"
to the root element of the application (the div all my apps components are rendered under, but not the modal), but it does not update the tab index or disable every focusable element.
However the React modal traps the keyboard focus, so the user can't tab out of the modal and clicking the background closes the modal.
So my question is:
Is this actually an issue I need to fix? Or is this a false positive as the tool doesn't have knowledge of the modal trapping focus?
If this does need to be fixed, is my only option to manually update the tab index or disable every focusable element?
Thanks!
The HTML when the modal is open looks kinda like this:
<div data-react-modal-body-trap="" tabindex="0" style="position: absolute; opacity: 0;"></div>
<div id="root" aria-hidden="true">application content</div>
<div class="ReactModalPortal">
<div class="ReactModal__Overlay ReactModal__Overlay--after-open modal-overlay-6fODnA">
<div tabindex="-1" role="dialog">modal content</div>
</div>
</div>
Short Answer
Adding aria-modal
to your modal will remove this warning.
Long Answer
It took me a while to realise why our modals do not have this warning but yours would as we employ similar markup. We use the aria-modal
property on our modals.
Axe has been updated to expect the aria-modal
property on a modal. aria-modal
has average support at the moment but it is a good practice as it counters developer mistakes (as screen reader / browser combos that do respect it will automatically trap focus for you!).
Hiding items outside a modal
The only way to truly hide everything is to add tabindex="-1"
to every single interactive item.
However in reality that is far more likely to cause a catastrophic accessibility issue if your JS function you use to add tabindex="-1"
to every interactive element encounters an issue and doesn't successfully revert the tabindex
or remove it. This would mean you leave parts of the page completely inaccessible!
Obviously you would then fail WCAG on the "Robust" part of POUR. Please don't do this.
The best compromise is to use aria-hidden
on the <main>
and <aside>
containers (any top level containers). Then use aria-modal
on your modal as this will trap focus in some browser / screen reader combos. That combination of aria
will provide the highest coverage for browser support.
Finally you should manage focus for people using the tab
key. This is our backup in case the above methods fail and for people not using a screen reader (i.e. people with dexterity or accuracy issues who can't use a mouse.)
If you need information on how to trap the tab focus within a modal I will provide a code sample but it is pretty straight forward.
Managing tab key focus will not stop screen reader users or misbehaving plugins from getting outside your modal (if the other methods fail) but believe me, if they have a problem with your site after you implement the above they will have bigger problems on other sites.
inert - a further string to your bow?
Finally as another backup we add inert
to the items outside of our modal. Support isn't great, but every little helps!
You can polyfill it if you want but I don't think it has moved outside of the draft spec yet so we just use it as is.
It is purely there as yet another add in and (hopefully) to future proof our legacy applications as inert
is a much needed and easy to understand attribute. It blocks screen readers access to items without changing visual design (basically aria-hidden
but as a standard attribute, with the advantage that it effectively removes all children from the accessibility tree.)
Example
Try removing the aria-modal="true"
from the following example and running Axe, the warning will return.
<main aria-hidden="true" inert><a href="https://google.com">test</a></main>
<div class="modal" aria-hidden="false" aria-modal="true">
<label for="iTest">input test</label>
<input id="iTest"/>
</div>
这篇关于“咏叹调隐藏元素不包含可聚焦元素"显示模态时的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!