🧗‍♂️

aria-labelで始める、アクセシビリティ改善活動

2023/11/15に公開
5

本記事では、aria-labelを利用したアクセシビリティ改善についてまとめていきたいと思います。

アクセシブルなサービスとは

そもそもアクセシブルなサービスとは、どのようなサービス、実装を指すのでしょうか。
端的に表現するならば、「伝えたい情報が正しい文書構造によって実装されているサービス」だと考えます。

例えば以下のようなボタンの実装があったとします。

<button aria-label="削除">編集</button>

こちらがレンダリングされた結果です。
ボタンが"編集"として画面上に表示されているスクリーンショット

こちらがスクリーンリーダーの結果です。
(Macの場合command+F5でVoiceOverを使用することができます。)
スクリーンリーダーがボタンを"削除"と読み上げている状態のスクリーンショット

この例の場合、視覚的な情報と、支援技術を介して得られる情報とで差異が産まれてしまっています。これはアクセシブルではありません。(例外[1]もあります。)
この例の場合、ボタンの働きが編集であれば、スクリーンリーダーにより取得した削除という情報は誤りになります。

スクリーンリーダーのような支援技術は、アクセシビリティツリーを元に情報の処理・出力を行います。
このアクセシビリティツリーは、DOMツリーという文書構造を変換したものです。
したがって、適切な文書構造で実装されているサービスは、多くのユーザーにとって使いやすく、アクセシブルなサービスであると言えます。

アクセシビリティツリーとは

WICG[2]文書では下図のように説明しています。この図が示すようにブラウザはHTMLからDOMツリーを生成し、それをアクセシビリティツリーという文書構造に変換します、そして支援技術に情報を伝達し、スクリーンリーダーであれば音声に、点字ディスプレイであれば点字に変換します。
支援技術がアクセシビリティツリーの情報を基にして、ユーザーに対する出力を行っているところがポイントです。

ウェブページのアクセシビリティの情報伝達の流れを説明する図。HTMLからDOMツリーが生成され、さらにアクセシビリティツリーに変換されるプロセスを示し、最終的に支援技術を通じてユーザーに情報が提供される流れが描かれています
画像引用元: https://github.com/WICG/aom/blob/gh-pages/explainer.md#background-dom-tree-accessibility-tree-and-platform-accessibility-apis

アクセシビリティツリーはDeveloper Toolsで確認することができます。
ref: https://developer.chrome.com/ja/blog/new-in-devtools-98/#a11y-tree

では、先ほどの実装をDeveloper Toolsで確認してみましょう。

Developer ToolsのAccessibilityペインで"編集"と表示されたボタンが"削除"というによって識別されている状態を示すスクリーンショット

画像からアクセシビリティツリーが階層構造になっていることが分かると思います。
いくつか情報の整理をしたいと思います。

アクセシビリティツリーから得られる情報は以下です。(ここでは、オブジェクトに含まれる多くの状態の中から特に重要なものに焦点を当てます)

  • 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>

Developer ToolsのAccessibilityペインで"閉じる"というaria-labelが付与されたSVGアイコンを含むボタンを確認しているスクリーンショット

  • StaticTextで内容が十分に説明されていない場合のbutton
    要素内のテキストだけでは、その機能や目的が十分に伝わらない場合があります(デザインの兼ね合いでテキストを短くする必要があることもあったり)。
    aria-labelを使用して、ボタンの機能を明確に伝えることができます。
<button aria-label="アカウント詳細">
  詳細
</button>

Developer ToolsのAccessibilityペインで"アカウント詳細"というaria-labelによって識別されている"詳細"ボタンのスクリーンショット

  • ダイアログ
    ダイアログを使用する際、ダイアログの目的や内容を明確に伝えることが重要です。
    aria-labelは、その目的を効果的に伝えるのに役立ちます。
<div role="dialog" aria-label="プライバシーポリシーの更新">
  <p>プライバシーポリシーが更新されました。</p>
  <button>了解</button>
</div>

Developer ToolsのAccessibilityペインで"プライバシーポリシーの更新"というaria-labelによって識別されているダイアログのスクリーンショット

ダイアログに可視のラベルが存在する場合は、aria-labelledbyを利用して、ダイアログの見出しになるテキスト要素のIDを参照し、そのテキストをダイアログのラベルとして使用します。

<div role="dialog" aria-labelledby="dialog-title">
  <h2 id="dialog-title">ユーザー設定</h2>
  <p>ユーザー設定を行なってください</p>
  <button>閉じる</button>
</div>

Developer ToolsのAccessibilityペインにて、"ユーザー設定"というタイトルを示す要素にaria-labelledby属性を用いてリンクしたダイアログを確認しているスクリーンショット

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
    • W3Cの中の団体であるWAIによって提供されている、アクセシビリティ向上のためのガイドライン
    • ARIAの使用に関する包括的なガイド、具体的な実装例などがあるので、基本迷ったらこれを見れば良さそう
  • デジタル庁GOV.UKなどの国や政府が運営しているサイト
    • 国や政府が運営しているサイトは、多様なユーザーが利用することを想定した実装になっているので、アクセシビリティが優れていることが多いです。
  • Radix UI
    • APGに基づいて実装されたコンポーネントライブラリ。
    • playgroundにRadix UIを利用して実装された一通りのコンポーネントがあるので、僕はよくそこを覗いて参考にしてます。
  • SmartHR Design System
    • アクセシビリティを考慮したデザインシステムが実装されている
  • accrefs
    • ウェブアクセシビリティに関する参考資料が色々まとめられていて便利

まとめ

今回はaria-labelを用いたアクセシビリティ向上についての記事でした。
自分自身、アクセシビリティへの理解を深めることがフロントエンドエンジニアとしてのひとつのブレークポイントであったと感じているため、なるべく初学者にも分かりやすい内容にすることを心がけました。
フロントエンドはユーザーとのエンドポイントになる部分なので、フロントエンドエンジニアとして誰もが使いやすいサービスを提供できるよう、アクセシビリティを考慮した実装を心がけたいと思います!

間違いなどあればご指摘ください!🙏🏻

脚注
  1. デジタル庁のサイトでは、支援技術を用いたユーザーのナビゲートのため、表示はされないが読み上げを目的とした要素があったりする ↩︎

  2. W3Cのコミュニティーグループのひとつで、新しいウェブの技術のアイデアについて議論し、発展させる場を提供しています。https://wicg.io/ ↩︎

  3. https://www.w3.org/TR/html-aria/#docconformance ↩︎

  4. https://ja.wikipedia.org/wiki/大いなる力には、大いなる責任が伴う ↩︎

Discussion

もんどもんど

「ご指摘ください!」とありますので、2点ほど。

1つめは、

aria-labelの指定がない場合は、StaticTextからの推測になります。

についてですが、(後述の)HTML-AAM仕様の4. Accessible Name and Description Computationでは、Nameがどう計算されるのかが記載されています。
button要素の場合は
https://www.w3.org/TR/html-aam-1.0/#button-element-accessible-name-computation

3. Otherwise use the button element subtree.

とあるように、サブツリー、つまりStaticTextから計算されますから、推測という言葉は当てはまらないのではないでしょうか。

MDNの日本語版がいっているように、
https://developer.mozilla.org/ja/docs/Learn/Accessibility/WAI-ARIA_basics

一点忘れてはいけないのが、 WAI-ARIA は必要な場合のみ使用するという点です。 理想的には、スクリーンリーダーのユーザーの理解に必要となる意味論の提供は、常に ネイティブの HTML 機能 を使用して行うべきです。

つまり言いかえると、<button aria-label="削除">編集</button>の場合は、StaticTextさえ提供すればよく、わざわざaria-label属性を用いてNameを上書きする必要はないということになるかと思います。

img要素の名前付けではalt属性を使用するのが適切です。

と言われているように、HTML-AAM仕様のimg要素のセクションでは、
https://www.w3.org/TR/html-aam-1.0/#img-element-accessible-name-computation

1. If the img element has an aria-label or an aria-labelledby attribute [...].
2. Otherwise use alt attribute, even if its value is the empty string.

とあるように、img要素のNameはalt属性から計算されるものであり、aria-label属性で強制的に上書きすると解釈できることからもわかるかと思います。


2つめはStateで

HTML要素は、それぞれデフォルトで暗黙的なセマンティクスを持っています。[3]。

として https://www.w3.org/TR/wai-aria-1.2/#implicit_semantics を挙げられていますが、このセクションの最後の段落に

Therefore, implicit WAI-ARIA semantics need to be defined in a normative specification, such as the host language specification or the Core Accessibility API Mappings.

とあるように、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からも明らかかと思います。

ご参考まで。

wozittowozitto

ご指摘ありがとうございます!🙇🏻‍♂️

1点目についてはたしかに"推測"ではなく、"計算"という表現が適切でしたね😥修正しておきます。

<button aria-label="削除">編集</button>の場合は、StaticTextさえ提供すればよく、わざわざaria-label属性を用いてNameを上書きする必要はないということになるかと思います。

こちらに関しては、その通りなのですが、間違った実装例の一つとして挙げさせてもらっています。
セクション「aria-labelを使ってみよう」の「StaticTextで内容が十分に説明されていない場合のbutton」のタイトル通り、StaticText(サブツリー)でbuttonの働きが十分に説明されている場合はaria-labelは不要かと思います。

2点目については、ここで主張したいのは「implicit WAI-ARIA semanticsの仕様」ではなく「デフォルトで暗黙的なセマンティクスを持っているんだよ」といったことなので以下リンクを参照しています🙏🏻
https://www.w3.org/TR/wai-aria-1.2/#implicit_semantics

もんどもんど

返信ありがとうございます。

こちらに関しては、その通りなのですが、間違った実装例の一つとして挙げさせてもらっています。

はい、そのことは承知の上ではありました(というのは最初のコメントではわからないですよね、すみません…)

1つめに関しては、wozittoさんと認識はあっていると思うのですが、その上で、「SVGアイコンボタン」の例は誤りではないですが、ベストとも言えないのではないでしょうか?
SVGは画像なわけですから、以下のコードのように画像の代替テキストを提供するのがセマンティックスからは筋ではあるのかなと思うのです。

<button>
  <svg role="img" width="24" height="24" viewBox="0 0 24 24">
    <title>閉じる</title>
    <path d="M0 0h24v24H0z" fill="none"/>
    <path d="M6 6l12 12M6 18L18 6" stroke="#000" stroke-width="2"/>
  </svg>
</button>

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

wozittowozitto

はい、そのことは承知の上ではありました(というのは最初のコメントではわからないですよね、すみません…)

いえいえ、こちらこそ理解が及ばず失礼しました。

なるほど、たしかにSVG要素にtitle要素を持たせて、aria-labelを使用せず実装できるならそれにこしたことはないですね。
もんどさんの実装を参考にしたいと思います。

しかし、SVG要素にtitle要素を持たせた実装を、Safariでスクリーンリーダー(MacのVoiceOver)を用いて動作確認したところ、title要素が読み上げられないことが判明しました。

調べてみると、どうやらインタラクティブな要素内のSVG画像の名前(svg要素内のtitleなど)の読み上げはブラウザ間で実装の違いがあり、読み上げに失敗することがあるみたいです。
https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html#:~:text=SVGs within links and buttons

なので代替策として、aria-labelの使用したいと考えました。
aria-labelを用いる場合、button要素での指定もsvg要素での指定も同等の選択になると考えていたのですが、アプリケーション全体での再利用性を考慮すると、親要素で名前を補足するよりは、子要素に直接代替テキストを付与する方が適切だと思いました。
なので結論、SVG要素にaria-labelを指定するのが最良だと考えています。(この実装の場合、chrome, safari, firefox, edge で正常に読み上げが行われることを確認しました)

<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>

2つ目について
なるほどです、たしかに「デフォルトで暗黙的なセマンティクスを持っています」ということを主張したいのであれば、参照先としてはWAI-ARIAではなく、ARIA in HTMLが適切ですね。
以下に参照先を変更しておきます!ありがとうございます🙏🏻

https://www.w3.org/TR/html-aria/#docconformance

もんどもんど

コメントありがとうございます。

なので結論、SVG要素にaria-labelを指定するのが最良だと考えています。

はい、落としどころとして、そうするのがよいのかなと思います。

以下に参照先を変更しておきます!ありがとうございます🙏🏻

こちらこそ、ありがとうございました。