😗

Web Componentのaria、外に書くか中に書くか

2021/08/10に公開
  • 外に書く
  • 中に書く

何の話

こうか

<x-list role="list">
  <x-listitem role="listitem"></x-listitem>
</x-list>

それともこうか

<x-list>
  #shadow-root
    <div role="list">
      <slot></slot>
    </div>
  <x-listitem>
    #shadow-root
      <div role="listitem">
        <slot></slot>
      </div>
     リストだよ
  </x-listitem>
</x-list>

aria attributesをShadow DOMの内側に書くか、Light DOM側に書くか。
そしてそれをlighthouseやaxe-coreでテストする際のTIPS.

何が問題か

a11yにおけるaria-required-parentルール

Certain ARIA roles must be contained by particular parent elements.

特定のARIAロールは、特定の親要素に含まれている必要があります。listlistitemなど。勿論元のHTML Elementである<ul>, <li>の関係も同じです。
list直下の子要素にはlistitemが設置されなくてはならず、<table>の子要素には<tr>, <thead>などのテーブル要素が必要です。この時、間にdiv要素など挟むことはできません。

ルールから外れた文書構造はlighthouseなどのa11yをチェックするツールで怒られます。マシンリーダビリティな構造のためには避けられないルールの一つでしょう。

このルールをWeb Componentで考えてみます。Web Componentでリストを提供する場合、大抵の設計ではlistとlistitem部分は分離されます。

<x-list>
  <x-listitem>ここは自由に書けるslot部分</x-listitem>
</x-listitem>

スッキリしていますね。listitem部分をattributeでArrayとしてブッこむ設計はあまり見ないと思います。

このリスト、a11y的に正しく書くにはどのように設計すれば良いのでしょうか。

外に書く

<x-list role="list">
  <x-listitem role="listitem"></x-listitem>
</x-list>

Light DOMとして見たら正しそうです。が、

上書きされうるattributeをコンポーネント自身が管理していいのか?

Custom Elementのそれ自身のタグ、つまりhost部分はLight DOMに存在するため、外部から容易に変更可能です。そんな部分で自身のa11y要素を管理して良いのかという問題があります。

また、 roleがhost部分に存在し、aria-describedbyがShadow DOM内部に都合上存在する場合なども考えなくてはいけません。そのような場合は連携するElementもslotでの設計が必要になります。

中に書く

今度はaria attributesをShadow DOMの中に書いてみます。

<x-list>
  #shadow-root
    <div role="list">
      <slot></slot>
    </div>
  <x-listitem>
    #shadow-root
      <div role="listitem">
        <slot></slot>
      </div>
     リストだよ
  </x-listitem>
</x-list>

どう見てもこれはlist -> listitemという構造ではなく、間にslot, x-listitemが挟まっていますが、しかし少なくともChromeのlighthouseはOKと言ってくれます。

スクリーンリーダーでもlist -> listitemであると認識してくれるので、実用上は問題無さそうです。

最新のaxe-coreで警告が出る

これよ。ちなみに同じくaxe-coreを使っているはずのChrome最新版(92.0.4515.131時点)でのlighthouseでは問題ありません。これはバージョンが関係していると思われますが、誰か知ってる方いらしたら教えて下さい。

a11yとして実用上どちらでも問題は無いので(無いはず)、自分は中に書きたいんだ!という意思を持った方はtestの設定でこのルールをoffにすれば良さそうです。

実用例

carbon

https://web-components.carbondesignsystem.com/?path=/story/components-list--ordered

carbonはShadow DOMの中に書いている模様。

shoelace

https://shoelace.style/components/menu-item

shoelaceも中に書いているようです。

結論

現状、業界としては中派が多いようです。ここで一番の問題はaxe-coreのa11yチェックで警告が出ること。これが問題ないという結論が出せればこのままShadow DOMの内側にaria attributesを書いても良さそうです。以前のバージョンでは出なかった警告のため、今後のバージョンアップでまた変更があるのを期待するか、実用上問題無いから無視しても良いと結論付けるかの意思が必要ですね。

Discussion