😗

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的に正しく書くにはどのように設計すれば良いのでしょうか。

外に書く

役割をはっきりさせるためにroleを書いてみましょう。

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

Light DOM(shadow DOMなしのDOM構造)として見たら正しそうです。が、

役割はコンポーネント自身が決定するべきでは?

roleを外側からいちいち書く、ましてや実装者の思惑で変更容易な部分にa11y要素の管理を任せていいのかという問題があります。

また、 roleがLight DOM側に存在するのに、aria-describedbyがShadow DOM内部に都合上存在する場合なども考えなくてはいけません。Shadow DOMはその中に実装を隠蔽された構造で、外側のariaと内側のariaが連携してくれる挙動は期待できません。そのような場合は連携する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