NVDA无法读取带role="listitem"的div元素的aria-label问题
解决NVDA下listitem元素优先读取内部文本而非aria-label的问题
我之前碰到过一模一样的NVDA兼容问题,这是因为不同屏幕阅读器对ARIA属性的优先级处理逻辑有差异:JAWS和Narrator会优先遵循你设置的aria-label,但NVDA对于带有role="listitem"的元素,会默认优先读取其可见的子元素文本内容,哪怕你指定了自定义标签。
这里有两个亲测有效的修改方案:
方案1:用aria-hidden隐藏内部文本
给所有内部子元素添加aria-hidden="true",明确告诉NVDA忽略这些内容,只读取外层的aria-label:
<div role="listitem" aria-label="Hello World" tabindex="0"> <div aria-hidden="true">A</div> <div aria-hidden="true">b</div> <div aria-hidden="true">c</div> <div aria-hidden="true">d</div> </div>
这个方案简单直接,不会影响视觉显示,只是屏蔽了屏幕阅读器对内部文本的读取。
方案2:改用aria-labelledby关联隐藏标签(更稳妥的语义化方案)
如果担心aria-hidden可能带来的其他兼容问题,也可以创建一个视觉隐藏的元素存放自定义标签,然后用aria-labelledby关联它:
<!-- 视觉隐藏的标签元素 --> <div id="custom-label" style="position:absolute;clip:rect(0 0 0 0);width:1px;height:1px;margin:-1px;overflow:hidden;">Hello World</div> <!-- 外层listitem元素 --> <div role="listitem" aria-labelledby="custom-label" tabindex="0"> <div>A</div> <div>b</div> <div>c</div> <div>d</div> </div>
这种方式更符合无障碍语义规范,而且在所有主流屏幕阅读器(包括NVDA、JAWS、Narrator)里的表现一致。
另外补充一点:如果你的外层元素是放在真实的<ul>或<ol>列表里的,其实可以直接用<li>标签代替div role="listitem",再配合上面的方案,语义化会更好,也能减少ARIA属性的使用。
内容的提问来源于stack exchange,提问作者maxx777
相关产品推荐
相关产品推荐

