❄️

UIのアクセシビリティ対応、こんな時はどう書く ?~WAI-ARIAとか~

2022/08/26に公開

Reactであんなものやこんなものを作っている最中のメモ書き。高頻度更新。

隠したい

aria-hidden="true"

SR-Userから隠す

tabindex="-1"

KB-Userがfocusできないようにする

隠し持ちたい

aria-haspopup="true"

ここを押せば何かが現れるよ!という意味

偽装したい

セレクトボックスとして

role="combobox"

コンボボックスとして読み上げ

コンボボックスとは

入力と選択が一体となっており、リストから項目を選択することも、テキストを直接入力することもできるものを指す。

aria-autocomplete="list"

オプションのリストが表示されることをSR-Userに示す

aria-expanded="false|true"

メニューが展開されていればtrue、折り畳まれていればfalseを設定することで、SR-Userにその状態を伝えてくれる

role="listbox"

メニューがリストボックスであることを示す

role="option"

リストボックスの選択肢であることを示す

aria-selected="true"

選択されていればtrue、そうでなければfalseを設定しておくことで、SR-Userにその旨を伝えてくれる

タブメニューとして

関連付けが肝心。どのタグに何を加えるべきかを把握するため、ReactのJSX部分を示す。

<ul role='tablist'>
  <li role='presentation'>
    <a
      href='#panel01'
      role='tab'
      aria-controls='panel01'
      aria-selected='true'
      aria-expanded='true'
      id='tab01'
    >
      Tab 1
    </a>
  </li>
  <li role='presentation'>
    <a
      href='#panel02'
      role='tab'
      aria-controls='panel02'
      aria-selected='false'
      aria-expanded='false'
      tabIndex={-1}
      id='tab02'
    >
      Tab 2
    </a>
  </li>
</ul>
<div
  id='panel01'
  aria-labelledby='tab01'
  role='tabpanel'
  aria-hidden='false'
>
  <h2 tabIndex={0}>Panel 1</h2>
  <DummyText500W />
</div>
<div
  id='panel02'
  aria-labelledby='tab02'
  role='tabpanel'
  aria-hidden='true'
>
  <h2 tabIndex={0}>Panel 2</h2>
  <DummyText500W />
</div>

ulタグにrole='tablist'

これはただのリストじゃない。この中に並んでいる子要素はタブ(切り替え時のクリック部分)として機能するよ〜的な

liタグにrole='presentation'

role='presentation'は要素の元々の意味を取り除く特別なロール、らしい。

ulがただのリストじゃないのだから、liも普通のリストアイテムではないのである。

ここでは、本質的にタブとして機能するのは中のa要素で、しかしulの中に直接aタグをぶち込むわけにはいかないため、liで囲っているだけ。
そんなのはこちらの都合であり、ユーザ側からしたらliは無意味な要素なので、このliタグは無視してね〜と明言している。

liの中のaタグにrole='tab'

これはただのリンクじゃない、パネル切り替えのボタン(タブ)として機能するよ〜的な

タブにaria-controls="パネルのid" && パネルにaria-labelledby='タブのid'

ここを押すと何が読めるようになるのかを明示するリレーションシップ。

タブにaria-selected='true | false'

選択されているかどうか。
選択されているタブのみtrueにする。これはJSによる制御が必要。

タブにaria-expanded='true | false'

展開されているかどうか。
開かれているパネルに対応するタブのみtrueにする。これもJSで切り替え。

パネルにaria-hidden='true | false'

隠れているかどうか。
開かれて読める状態になっているパネルのみfalseとする。

tabindexによるキーボード操作への対応

タブメニューは、キーボード操作の場合に次のように閲覧できることが理想的らしい。

  • 矢印(ArrowLeft, ArrowRight)キーでタブを切り替え
  • タブにfocusされている状態でTabキーを押すと、パネルにfocusが移る
  • パネルにfocusされている状態でShift + Tabキーを押すと、タブに戻る

タブ -> パネル

パネル(ここではdiv)の中の最初の要素(ここではh2)にtabindex="0"を指定してfocus可能にする。

パネル -> タブ

今開いているパネルに対応するタブのみfocus可能にするため、関係のないタブにはtabindex="-1"を付与しておく。

タブ <-> タブ

横方向矢印キーが押されたことを検知して、focusを隣にずらし、focusが外れたタブにtabindex='-1'を指定する処理をJSで組む。

その他、UIの操作性を改善する属性

autocomplete="off"

ブラウザに入力候補を表示させなくする

autocapitalize="none"

最初の文字が自動的に大文字になるのを防ぐ

参考文献 ~日本語でアクセシビリティを学ぶ~

まだまだ少ないのが現状だが、日本にもいくつかアクセシビリティに言及した書籍が存在する。

アクセシビリティって打つの面倒くさいな…a11yって書くね。

コーディングWebアクセシビリティ

ガチでa11y対応するなら正直唯一の選択肢。主にWAI-ARIA解説書だが、網羅率(?)が他書の比にならない。

https://www.borndigital.co.jp/book/6251.html

Form Design Patterns

アクセシビリティとUXを考慮したUI&フロントエンドシステム作成パターン集。
よくあるUIが完全否定されていたり、本気でa11y対応するのってこんなに大変なんだ…という衝撃もあったり。
これを読んでしまえば、もう適当な設計や実装ができなくなる。個人的にはすべてのフロントエンド開発者に読んでほしい書籍No.1。

https://www.borndigital.co.jp/book/16354.html

Every Layout

メディアクエリを使わずにレスポンシブデザインを実現する、的な書籍。
モーダルウィンドウやカルーセルの雛形として使えるデザインパターンも掲載されており、きちんとa11y対応がなされている。
見た目のためのCSSを書いているうちにいつの間にかアクセシビリティを損なう、そんな盲点に気付ける本。

https://www.borndigital.co.jp/book/24204.html

HTML+CSSコーディングの強化書

タブメニューの実装事例とか、アクセシビリティに配慮したフォームカスタマイズの作法とか。
a11y解説は一部のみだが、それ以外のコンテンツもとにかく強い。Webデザイナ必読かもしれない。

https://books.mdn.co.jp/books/3221303016/?page=2&direct=1

HTML解体新書

最後の章がa11y解説。
具体的な実装方法が充実しているわけではないが、一体何を考慮すべきかというリテラシーを学ぶのに最適。

https://www.borndigital.co.jp/book/25999.html

Discussion