aria-labelで始める、アクセシビリティ改善活動
本記事では、aria-label
を利用したアクセシビリティ改善についてまとめていきたいと思います。
アクセシブルなサービスとは
そもそもアクセシブルなサービスとは、どのようなサービス、実装を指すのでしょうか。
端的に表現するならば、「伝えたい情報が正しい文書構造によって実装されているサービス」だと考えます。
例えば以下のようなボタンの実装があったとします。
<button aria-label="削除">編集</button>
こちらがレンダリングされた結果です。
こちらがスクリーンリーダーの結果です。
(Macの場合command+F5でVoiceOverを使用することができます。)
この例の場合、視覚的な情報と、支援技術を介して得られる情報とで差異が産まれてしまっています。これはアクセシブルではありません。(例外[1]もあります。)
この例の場合、ボタンの働きが編集であれば、スクリーンリーダーにより取得した削除という情報は誤りになります。
スクリーンリーダーのような支援技術は、アクセシビリティツリーを元に情報の処理・出力を行います。
このアクセシビリティツリーは、DOMツリーという文書構造を変換したものです。
したがって、適切な文書構造で実装されているサービスは、多くのユーザーにとって使いやすく、アクセシブルなサービスであると言えます。
アクセシビリティツリーとは
WICG[2]の文書では下図のように説明しています。この図が示すようにブラウザはHTMLからDOMツリーを生成し、それをアクセシビリティツリーという文書構造に変換します、そして支援技術に情報を伝達し、スクリーンリーダーであれば音声に、点字ディスプレイであれば点字に変換します。
支援技術がアクセシビリティツリーの情報を基にして、ユーザーに対する出力を行っているところがポイントです。
アクセシビリティツリーはDeveloper Toolsで確認することができます。
ref: https://developer.chrome.com/ja/blog/new-in-devtools-98/#a11y-tree
では、先ほどの実装をDeveloper Toolsで確認してみましょう。
画像からアクセシビリティツリーが階層構造になっていることが分かると思います。
いくつか情報の整理をしたいと思います。
アクセシビリティツリーから得られる情報は以下です。(ここでは、オブジェクトに含まれる多くの状態の中から特に重要なものに焦点を当てます)
- Role: button
- Name: 削除
- StaticText: 編集
- State: (Default)
それぞれの属性について詳しく説明します。
Role
日本語で訳すと「役割」になります。
そのままの意味で、この属性は要素の目的や機能を示します。
この例ではbutton
というRoleが割り当てられていて、これは要素がボタンであることを示しています。
Name
要素のラベルや識別名を示す属性です。
要素が具体的に何を示しているのか、まだどのような働きを持つものなのかをユーザーに伝えます。
スクリーンリーダーなどの支援技術では、この属性が要素の識別に用いられます。
この例では、aria-label
によって設定された「削除」という名前が、実際に表示されている「編集」というテキストよりも優先されています。
aria-label
の指定がない場合は、StaticTextからの計算になります。
StaticText
要素に直接書かれたテキストです。
この例では、「編集」というテキストがボタンに書かれています。しかし、Name属性によって異なる名前が指定されているため、このテキストはスクリーンリーダーによって読み上げられません。
State
要素の状態や振る舞いを示すものです。
HTML要素は、それぞれデフォルトで暗黙的なセマンティクスを持っています。[3]。
例えば、button要素はデフォルトで「focusable(フォーカス可能)」という状態を持っています。
そのため、実装上では明示的にfocusableを指定していないものの、ボタン要素は標準でフォーカス可能な状態として扱われています。
Nameの指定を見て分かる通り、Name属性の指定では、aria-label
によって設定された「削除」という名前が、要素内の「編集」というStaticTextより優先されていることがわかります。
つまりaria-label
を使用することで、Name属性に著者名義の名前(代替テキスト)を指定することができるのです。
aria-labelを使ってみよう
実際にaria-label
を使用する例をいくつか紹介します。
-
SVGアイコンボタン
SVGアイコンは視覚的には理解しやすいですが、支援技術を利用するユーザーからは機能が伝わりにくいことがあります。
aria-label
を使用することで、ボタンの機能を明確に伝えることができます。
また、role="img"
を指定して、SVGが画像として機能していることを明示することができます。
これは特に、SVGが装飾目的ではなく、意味的に重要な情報(アイコンやロゴなど)を示している場合に重要です。
<button>
<svg role="img" aria-label="閉じる" width="24" height="24" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M6 6l12 12M6 18L18 6" stroke="#000" stroke-width="2"/>
</svg>
</button>
-
StaticTextで内容が十分に説明されていない場合のbutton
要素内のテキストだけでは、その機能や目的が十分に伝わらない場合があります(デザインの兼ね合いでテキストを短くする必要があることもあったり)。
aria-label
を使用して、ボタンの機能を明確に伝えることができます。
<button aria-label="アカウント詳細">
詳細
</button>
-
ダイアログ
ダイアログを使用する際、ダイアログの目的や内容を明確に伝えることが重要です。
aria-label
は、その目的を効果的に伝えるのに役立ちます。
<div role="dialog" aria-label="プライバシーポリシーの更新">
<p>プライバシーポリシーが更新されました。</p>
<button>了解</button>
</div>
ダイアログに可視のラベルが存在する場合は、aria-labelledby
を利用して、ダイアログの見出しになるテキスト要素のIDを参照し、そのテキストをダイアログのラベルとして使用します。
<div role="dialog" aria-labelledby="dialog-title">
<h2 id="dialog-title">ユーザー設定</h2>
<p>ユーザー設定を行なってください</p>
<button>閉じる</button>
</div>
aria-labelの利用で気をつけること
このようにアクセシビリティ向上のために有用なaria-label
ですが気をつける点があります。
それは、大いなる力には大いなる責任が伴うということです👱🏼♂️
With great power comes great responsibility.[4]
APG(w3cによって提供されているアクセシビリティ向上のためのガイドライン)のRead Me FirstにもNo ARIA is better than Bad ARIAという記載がある通り、aria-label
を含むaria属性はそれ自体が強い仕様を強いるものなので、誤った使い方をしてしまうと、支援技術を用いた体験に破壊的な影響を与える可能性があります。
なのでaria-label
を含むaria属性を使用する際には、その使用が適切かどうかしっかり検討して安全に使用する必要があります。
そこでいくつかaria-label
を使用する際の注意点について説明します。
アクセシブルな名前が必要かどうかは要素によって異なる
全てのロールがaria-label
による名前付けを必要とするわけではありません。
名前付けが必要かどうかはロールによって異なります。場合によっては名前付けが禁止されている、または非推奨であることもあります。
また、aria-label
以外の方法でアクセシブルな名前を提供する方が適切な場合もあります。
例えば、img要素の名前付けではalt属性を使用するのが適切です。また、dialog要素での例のように、aria-labelledby
を使用しての参照渡しが適切な場合もあります。
どのロールがどのような指定を必要としているのかは、APGのAccessible Name Guidance by Roleで確認することができます。
アクセシブルな名前は短く簡潔に説明すること
aria-label
は、短く簡潔な説明に留めることが重要です。長すぎる名前は、ユーザーにとってわかりにくくなる恐れがあります。
ボタンやリンクの機能を簡潔かつ明確に説明するように心掛けましょう。
-
good 👍🏻
- 詳細を表示
- 検索
-
bad 👎🏻
- 詳細
- このボタンをクリックすると、検索機能が起動し、情報を探すことができます。
長い説明を必要とする場合は別途UIを準備する必要がある
もし要素に長い説明が必要な場合、aria-label
だけに頼るのではなく、別途説明のためのUIを準備することを検討してください。
たとえば、追加情報を提供するためのツールチップやポップアップ、説明セクションなどを設けることが考えられます。
実際に支援技術を使用して動作確認を行う
実際のところアクセシビリティの仕様はありますが、それを正しく解析できるかはブラウザの実装次第です。
なのでアクセシビリティが意図した通りに機能しているか判断するためには、Developer Toolsでアクセシビリティツリーを確認したり、実際に支援技術を使用して確認する必要があります。
参考になるサイト
個人的に普段の開発でお世話になっているアクセシビリティ学習のためのサイトをいくつか紹介したいと思います。
- APG
-
デジタル庁やGOV.UKなどの国や政府が運営しているサイト
- 国や政府が運営しているサイトは、多様なユーザーが利用することを想定した実装になっているので、アクセシビリティが優れていることが多いです。
-
Radix UI
- APGに基づいて実装されたコンポーネントライブラリ。
- Accessibilityについて
- playgroundにRadix UIを利用して実装された一通りのコンポーネントがあるので、僕はよくそこを覗いて参考にしてます。
- APGに基づいて実装されたコンポーネントライブラリ。
-
SmartHR Design System
- アクセシビリティを考慮したデザインシステムが実装されている
-
accrefs
- ウェブアクセシビリティに関する参考資料が色々まとめられていて便利
まとめ
今回はaria-label
を用いたアクセシビリティ向上についての記事でした。
自分自身、アクセシビリティへの理解を深めることがフロントエンドエンジニアとしてのひとつのブレークポイントであったと感じているため、なるべく初学者にも分かりやすい内容にすることを心がけました。
フロントエンドはユーザーとのエンドポイントになる部分なので、フロントエンドエンジニアとして誰もが使いやすいサービスを提供できるよう、アクセシビリティを考慮した実装を心がけたいと思います!
間違いなどあればご指摘ください!🙏🏻
-
デジタル庁のサイトでは、支援技術を用いたユーザーのナビゲートのため、表示はされないが読み上げを目的とした要素があったりする ↩︎
-
W3Cのコミュニティーグループのひとつで、新しいウェブの技術のアイデアについて議論し、発展させる場を提供しています。https://wicg.io/ ↩︎
Discussion
「ご指摘ください!」とありますので、2点ほど。
1つめは、
についてですが、(後述の)HTML-AAM仕様の4. Accessible Name and Description Computationでは、Nameがどう計算されるのかが記載されています。
button
要素の場合はhttps://www.w3.org/TR/html-aam-1.0/#button-element-accessible-name-computation
とあるように、サブツリー、つまりStaticTextから計算されますから、推測という言葉は当てはまらないのではないでしょうか。
MDNの日本語版がいっているように、
https://developer.mozilla.org/ja/docs/Learn/Accessibility/WAI-ARIA_basics
つまり言いかえると、
<button aria-label="削除">編集</button>
の場合は、StaticTextさえ提供すればよく、わざわざaria-label
属性を用いてNameを上書きする必要はないということになるかと思います。と言われているように、HTML-AAM仕様の
img
要素のセクションでは、https://www.w3.org/TR/html-aam-1.0/#img-element-accessible-name-computation
とあるように、
img
要素のNameはalt
属性から計算されるものであり、aria-label
属性で強制的に上書きすると解釈できることからもわかるかと思います。2つめはStateで
として https://www.w3.org/TR/wai-aria-1.2/#implicit_semantics を挙げられていますが、このセクションの最後の段落に
とあるように、HTMLのimplicit WAI-ARIA semanticsは別の仕様で定義されています。
HTMLの場合はHTML Accessibility API Mappings 1.0 (HTML-AAM)仕様https://www.w3.org/TR/html-aam-1.0/です。(これはWAI-ARIA 1.2仕様のAbstractからリンクされているWAI-ARIA Overview https://www.w3.org/WAI/standards-guidelines/aria/からたどることができるかと思います)
もっとも、実装者向けの情報はたいていの場合不要ですので、HTML-AAM仕様の制作者向けの焼き直しとなるARIA in HTML仕様https://www.w3.org/TR/html-aria/を当たることになると思います。
これらは、HTML Standardの3.2.4 Element definitions https://html.spec.whatwg.org/multipage/dom.html#element-definitionsにある、Accessibility considerationsからも明らかかと思います。
ご参考まで。
ご指摘ありがとうございます!🙇🏻♂️
1点目についてはたしかに"推測"ではなく、"計算"という表現が適切でしたね😥修正しておきます。
こちらに関しては、その通りなのですが、間違った実装例の一つとして挙げさせてもらっています。
セクション「aria-labelを使ってみよう」の「StaticTextで内容が十分に説明されていない場合のbutton」のタイトル通り、StaticText(サブツリー)でbuttonの働きが十分に説明されている場合は
aria-label
は不要かと思います。2点目については、ここで主張したいのは「implicit WAI-ARIA semanticsの仕様」ではなく「デフォルトで暗黙的なセマンティクスを持っているんだよ」といったことなので以下リンクを参照しています🙏🏻
返信ありがとうございます。
はい、そのことは承知の上ではありました(というのは最初のコメントではわからないですよね、すみません…)
1つめに関しては、wozittoさんと認識はあっていると思うのですが、その上で、「SVGアイコンボタン」の例は誤りではないですが、ベストとも言えないのではないでしょうか?
SVGは画像なわけですから、以下のコードのように画像の代替テキストを提供するのがセマンティックスからは筋ではあるのかなと思うのです。
2つめはこれもわたしの説明が下手だったのですが、
言いたかったこととしては、WAI-ARIAは「デフォルトで暗黙的なセマンティクス」という概念を定義しているのであって、HTMLの「デフォルトで暗黙的なセマンティクス」を定義していない、ということです。
いいかえると、WAI-ARIAで定義されたロールが、HTMLが定義する要素とどう対応しているのかは、WAI-ARIA仕様では決められていません。決めているの別の仕様です。
たとえば、HTMLの
button
要素のもつ暗黙セマンティクスがrole=button
であることは、ARIA in HTMLでわかります。https://www.w3.org/TR/html-aria/#el-button
いえいえ、こちらこそ理解が及ばず失礼しました。
なるほど、たしかにSVG要素にtitle要素を持たせて、aria-labelを使用せず実装できるならそれにこしたことはないですね。
もんどさんの実装を参考にしたいと思います。
しかし、SVG要素にtitle要素を持たせた実装を、Safariでスクリーンリーダー(MacのVoiceOver)を用いて動作確認したところ、title要素が読み上げられないことが判明しました。
調べてみると、どうやらインタラクティブな要素内のSVG画像の名前(svg要素内のtitleなど)の読み上げはブラウザ間で実装の違いがあり、読み上げに失敗することがあるみたいです。
なので代替策として、aria-labelの使用したいと考えました。
aria-labelを用いる場合、button要素での指定もsvg要素での指定も同等の選択になると考えていたのですが、アプリケーション全体での再利用性を考慮すると、親要素で名前を補足するよりは、子要素に直接代替テキストを付与する方が適切だと思いました。
なので結論、SVG要素にaria-labelを指定するのが最良だと考えています。(この実装の場合、chrome, safari, firefox, edge で正常に読み上げが行われることを確認しました)
2つ目について
なるほどです、たしかに「デフォルトで暗黙的なセマンティクスを持っています」ということを主張したいのであれば、参照先としてはWAI-ARIAではなく、ARIA in HTMLが適切ですね。
以下に参照先を変更しておきます!ありがとうございます🙏🏻
コメントありがとうございます。
はい、落としどころとして、そうするのがよいのかなと思います。
こちらこそ、ありがとうございました。