“[aria-hidden="true"] 元素包含可聚焦的后代”;解决这个问题的最佳方法?

问题描述 投票:0回答:3

我有一个简单的手风琴:

<div>
  <button aria-expanded='false' aria-controls='content'>
    Open accordion
  </button>
  <div id='content' aria-hidden='true'>
    This the accordion's hidden content.
  </div>
</div>

我使用 Javascript 打开/关闭手风琴并设置

aria-*
标签。

一切正常,但是当我在内容中添加链接时:

<div>
  <button aria-expanded='false' aria-controls='content'>
    Open accordion
  </button>
  <div id='content' aria-hidden='true'>
    This is the accordion's hidden content.
    <a href='https://www.google.com'>Go to Google</a>
  </div>
</div>

灯塔给了我这个:

[aria-hidden="true"] elements contain focusable descendents

在我看来,将

tabindex='-1'
添加到
a
标签可以解决问题:

<a tabindex='-1' href='https://www.google.com'>Go to Google</a>

但是,这使得元素“不可选项”,这不利于可访问性。

我可以使用 JavaScript 手动查询手风琴内容中的所有

a
标签,但我什至不确定这是否真的解决了“问题”还是一个肮脏的解决方法?还有更好的选择吗?

html accessibility wai-aria wcag
3个回答
13
投票

为什么会收到此警告?

此警告表明,尽管您使用了

aria-hidden="true"
,但如果子项可以接收焦点,大多数屏幕阅读器都会忽略父项上的
aria-hidden="true"
(考虑到开发人员错误、JavaScript 未正确加载等)。

如何解决?

我假设您正在使用上滑动画或类似的东西,这就是为什么您不简单地在内容上使用

display: none

如果您没有使用动画,那么只需

display: none
应用
aria-hidden="true"
时的内容即可(@Adam 在他的回答中向您展示了执行此操作的完美方法)。

更好的是,您可以直接在 div 上使用

display: none
,因为这会隐藏屏幕阅读器看不到的所有内容,因此您不需要在那里使用 WAI-ARIA!

我正在使用动画/过渡,因此不能隐藏所有内容。

如果您使用动画、不透明度更改等,这会阻止您简单地隐藏整个内容,那么您可以做的就是隐藏内容中的可聚焦内容

<div>

当您应用

aria-hidden="true"
时,我们可以使用 CSS 来执行此操作,然后在更改或删除
aria-hidden="true"
时取消隐藏可聚焦元素。

为了避免再次取消隐藏元素时出现“布局卡顿”,我建议使用

visibility: hidden
而不是
display: none
,因为这样会为隐藏项目分配空间,并且仍然对屏幕阅读器等隐藏它们。

#content[aria-hidden=true] a[href],
#content[aria-hidden=true] area[href], 
#content[aria-hidden=true] input:not([disabled]), 
#content[aria-hidden=true] select:not([disabled]), 
#content[aria-hidden=true] textarea:not([disabled]), 
#content[aria-hidden=true] button:not([disabled]), 
#content[aria-hidden=true] [tabindex]:not([disabled]), 
#content[aria-hidden=true] [contenteditable=true]:not([disabled]){
    visibility: hidden;
}

快速演示

了解我的意思的最简单方法是通过快速演示,按“切换 aria-hidden on”按钮,它将隐藏

#content <div>
中的所有可聚焦元素。

var btn = document.querySelector('#toggle-aria');
var contentDiv = document.querySelector('#content');


btn.addEventListener('click', function(){
    var self = this;
    if(contentDiv.getAttribute('aria-hidden') == "false"){
      self.innerHTML = "Toggle aria-hidden off";
      contentDiv.setAttribute('aria-hidden', "true"); 
    }else{
      self.innerHTML = "Toggle aria-hidden on";
      contentDiv.setAttribute('aria-hidden', "false"); 
    }
});
#content{
padding: 20px;
border: 1px solid #333;
}

#content[aria-hidden=true] a[href],
#content[aria-hidden=true] area[href], 
#content[aria-hidden=true] input:not([disabled]), 
#content[aria-hidden=true] select:not([disabled]), 
#content[aria-hidden=true] textarea:not([disabled]), 
#content[aria-hidden=true] button:not([disabled]), 
#content[aria-hidden=true] [tabindex]:not([disabled]), 
#content[aria-hidden=true] [contenteditable=true]:not([disabled]){
    visibility: hidden;
}
<br/><br/><button id="toggle-aria">Toggle aria-hidden on</button>

<p>When aria-hidden is set to true on the below div all focusable elements should disappear.</p>

<hr/>

<div id="content" aria-hidden="false">
    <a href="https://google.com">To Google</a><br/><br/>
    <label>An input
      <input />
    </label><br/><br/>
    <label>A Select 
      <select>
        <option>option 1</option>
        <option>option 2</option>
        <option>option 3</option>
      </select>
     </label><br/><br/>
     <label>A textarea
      <textarea></textarea>
    </label><br/><br/>
    <button>A button</button><br/><br/>
    <div tabindex="0">A fake button with tabindex</div><br/><br/>
    <div contenteditable="true">A div that is cotnent editable</div><br/><br/>
    <p>Only the labels and this paragraph should be the only things left showing when you toggle the aria-hidden to true</p>
    
</div>
<br/><br/>
<button>I am a button purely so you can see there is nothing focusable within the #content div if you "Tab"</button>

重要提示: 当您按下“打开手风琴”按钮时,您应该删除

aria-hidden
之前任何动画等。这是因为屏幕阅读器用户随后会尝试按 Tab(或通过屏幕阅读器快捷方式导航)进入内容。如果您删除
aria-hidden="true"
太晚,他们可能会跳过所有内容!


6
投票

简单的解决方案,使用 CSS

display:none
属性来删除元素的焦点:

#content[aria-hidden=true] {
   display:none;
}

这不仅有用,而且非常必要,因为我们不希望屏幕阅读器宣布不可见的事情。


0
投票

我刚刚将 tabindex="-1" 更改为 tabindex="1" 然后就可以正常使用了

<div class="modal fade" id="userModal" tabindex="1" role="dialog" aria-labelledby="userModalLabel" aria-hidden="false" aria-busy="true" >
</div

© www.soinside.com 2019 - 2024. All rights reserved.