【问题标题】:Custom elements and accessibility自定义元素和可访问性
【发布时间】:2014-06-30 17:12:13
【问题描述】:

我想使用当前的 Web 组件规范实现一个列表框小部件。此外,生成的列表框应符合 ARIA 标准。实例化列表框小部件应该很简单:

<x-listbox>
    <x-option>Option 1</x-option>
    <x-option>Option 2</x-option>
</x-listbox>

出于清洁和封装的目的,其他所有内容都应在 shadow dom 中渲染。为了实现这个小部件,注册了两个自定义元素&lt;x-listbox&gt;&lt;x-option&gt;&lt;x-listbox&gt; 的影子 dom 的*元素是 &lt;div&gt;,它带有 role=listboxaria-activedescendent 属性以实现可访问性(我不希望 &lt;x-listbox&gt; 元素上的这些属性,因为它们是实现详细信息。)

为了让aria-activedescendent 工作,需要在选项元素上设置 ID。将 id 直接放在 &lt;x-option&gt; 元素上不会有两个原因:首先,它会污染使用列表框小部件的文档的 id 命名空间。其次,更重要的是,id 不能跨影子边界工作(这是影子 dom 的目的之一),因此选项的 id 必须与 &lt;div&gt;aria-activedescendent 属性位于相同的影子 dom 中。

对此的解决方案是用另一个&lt;div&gt;(属于该shadow dom)包围每个&lt;x-option&gt;,在&lt;x-listbox&gt;的shadow dom中呈现为内容,在其上可以放置一个id。

我的问题是:这是正确的方法吗?如何使用自定义元素和 shadow dom web api 来实现?

【问题讨论】:

    标签: web-component wai-aria shadow-dom


    【解决方案1】:

    您可能应该通过创建select 元素(使用JavaScript)来更好地实现这一点。这应确保屏幕阅读器将其正确识别为从列表中选择值的输入。

    &lt;x-listbox&gt; 元素下方添加一个类似这样的select 元素:

    <select class="only-screenreader">
       <option>Option 1</option>
       <option>Option 2</option>
    </select>
    

    然后将aria-hidden="true" 添加到您的自定义&lt;x-listbox&gt; 元素中。

    最后应用 CSS 使屏幕阅读器选择元素不可见。

    .only-screenreader {
       position:absolute;
       left:-10000px;
       top:auto;
       width:1px;
       height:1px;
       overflow:hidden;
    }
    

    这是我的方法,但也许有更好的方法。

    【讨论】:

    • 虽然这在可访问性方面可行,但它违背了我的封装目标(因为不属于提供的 HTML 的选择元素会出现在轻量级 DOM 中)。其次,如果我尝试使用更复杂的小部件(例如,其选项包含多于一些文本的列表框),我将不得不用定制的符合 aria 的小部件替换 select 元素,这意味着我会将我的 x-listbox 翻倍。
    【解决方案2】:

    在提供的标记中,x-option 是在 light DOM 中,而不是 shadow DOM,所以它可以被 id 引用。为了避免污染 id 命名空间,我生成了一个随机的 id,该 id 是在组件加载时设置但可以替换的。这样,无论组件用户是否在其上设置了 id,我都可以通过 id 引用元素。 将每个选项包装在 div 中似乎是不必要的,并且可能会导致问题。此外,如果选项在 &lt;slot /&gt; 中,那根本不可能。

    【讨论】: