「絶対にdisabled属性を避けて、aria-disabled属性を使わなければならない」わけではありません

最近、「アクセシビリティを向上させたいなら、HTMLの `disabled` 属性ではなく、`aria-disabled` 属性を使うべき」という主張を見かけますが、本当にそうなのでしょうか？

## disabled属性を使っていても、スクリーンリーダーで要素を知覚できる

そのような主張をしている人、それを受け止めた人の中には「 `disabled` 属性を使った要素はスクリーンリーダで読めなくなる」と誤解している人が少なからず存在するように思われます。しかしこれは正しい理解ではありません。

たしかに、`disabled`属性を付加している `button` 要素や `input` 要素、 `select` 要素、 `textarea` 要素は、Tabキーによるフォーカスはできなくなります。

しかし、スクリーンリーダーはTabキーによるフォーカスとは独立した、スクリーンリーダー自身のカーソルを持ちます。スクリーンリーダーを起動しているときにTabキーを押すと、通常時と同じようにフォーカスが移動し、スクリーンリーダーのカーソルも追従して移動します。それとは別に、スクリーンリーダーはスクリーンリーダーのカーソルを移動させるキー操作があり、通常のTabキー押下でフォーカスしない場所にもカーソルを移動させることができます。

Tabキーではなく、スクリーンリーダーのカーソルを移動させる操作をすることによって、スクリーンリーダーでも `disabled` 属性をつけた要素を問題なく知覚することができます。

https://qiita.com/ymrl/items/11e78cd6fbfdae39de84

## `aria-disabled`属性だけではdisabledにはならない

そもそも `aria-disabled` 属性とは何者なのでしょうか。

名前が `aria-` で始まる名前の属性は、HTMLの属性ではありません。Accessible Rich Internet Applications (WAI-ARIA)という仕様で定められています。これは、Webアプリケーションのウィジェットの種類や状態をスクリーンリーダーのような支援技術に伝えるための仕様です。

- [Accessible Rich Internet Applications (WAI-ARIA) 1.2](https://www.w3.org/TR/wai-aria-1.2/)
- [Accessible Rich Internet Applications (WAI-ARIA) 1.2 日本語訳](https://momdo.github.io/wai-aria-1.2/)

WAI-ARIAは、HTML[^1]によって表現される多種多様で複雑なUIの情報を、スクリーンリーダーのような支援技術に伝えるための属性を定義しています。これらのWAI-ARIAの属性はHTMLの属性の最新版でも上位互換でもありません。

[^1]:WAI-ARIAの仕様はHTMLだけでなくSVGも「ホスト言語」として想定していますが、ここではわかりやすくするためにHTMLとだけ書いています。

WAI-ARIAの説明については、共著書の「[Webアプリケーションアクセシビリティ](https://webapp-a11y.com/)」にわかりやすいものがあるので、これを引用します（私が書いた部分ではないのですが）。

>かつては Web 上でアプリケーションとしての UI を作るには、HTML に定義されているフォームやボタンを組み合わせるしかありませんでした。しかし、それらで表現できる範囲は限定的で、機能や見た目はデスクトップアプリケーションと比べて見劣りしていました。そこで多くの Web アプリ ケーションでは、CSS やJavaScript を駆使して、より高機能で見た目も良い UI コンポーネントを実装するようになりました。
>
> しかし HTML には「メニューバー」「タブ」「ツールチップ」「ツールバー」など、デスクトップアプリケーションでは当たり前のように使われるウィジェットを直接表す語彙がありません。視覚的にそれらのウィジェットのように見えるものを作っても、スクリーンリーダーのような支援技術に対して、それがどんなウィジェットでどんな状態なのかという情報を伝えられないのです。
>
>こうした状況に対処していくために WAI-ARIA(ウェイアリアと発音します)があります。ARIA とは Accessible Rich Internet Applications の頭文字で、 その名のとおり Web アプリケーションをよりアクセシブルにするための、 W3C が発行している仕様です。WAI-ARIA を使うと、HTML の各要素に対して属性を記述する形で、前述のようなウィジェットに相当する役割を与える、そのウィジェットの状態の変化を伝える、DOM(Document Object Model) 上では離れた位置にある要素の変化を通知するといったことが可能になります。
>
>「[Webアプリケーションアクセシビリティ](https://webapp-a11y.com/)」より引用

 

WAI-ARIAがすることはウィジェットの種類や状態を伝えるだけであって、実際の見た目や挙動には変化を与えません。そのため、`aria-disabled` 属性を付けただけでは「disabledな状態」にはならず、見た目は「操作できそう」なまま、クリックやキーボードによる操作を受け付けてしまいます。

そのため、見た目を「操作できなさそう」にしたり、クリックやキーボードのイベントを無視するようにJavaScriptを書いたりする必要があります。実際、`aria-disabled`属性を使うことを推奨するどの記事でも、JavaScriptによって「disabledな状態」にする方法が紹介されています。

### 自分たちで実装することにはリスクが伴う

`disabled` 属性ひとつ書けば済んでいたものが、`aria-disabled` 属性とJavaScriptコードの両方を合わせなければいけなくなるということは、そのぶん実装の複雑度が上がるということです。アプリケーションの挙動を記述しているJavaScriptのイベントハンドラーの先頭にif文を増やしたり、あるいは「disabledな状態」を作るためにイベントハンドラーを新たに追加したりしなければなりません。

作業に漏れが発生してしまうリスクや、場所により指定方法やその内容が異なってコードが難解になったりするリスク、結果として新しいメンバーが開発に参画するときのコストが上がってしまうことなどのデメリットが考えられます。

また、一般論として、HTMLの範囲、ブラウザのデフォルトの挙動で実現できることを、JavaScriptを使って自分たちで再現しようとすることには大きなリスクが伴います。

支援技術での利用が難しくなる・不可能になるという大きなアクセシビリティの毀損に繋がることもあれば、たとえば「リンクを新しいタブで開きたい」というようなちょっとした便利さを奪うこともあります。WAI-ARIAを使えば自分たちで作った機能を機能をアクセシブルにできるとはいえ、WAI-ARIAを使って実装したものが本当にアクセシブルであるかは、実際の様々な支援技術を使ってかなり慎重に確かめなければなりませんし、WAI-ARIAを使わないで済むのであれば使わないほうが良いのです。

Web標準に新しい機能が追加されるとき、我々のまだ知らない新しいブラウザ、デバイス、支援技術が登場するとき、それらを作る人たちは既存のWeb標準を参照し、機能を保とうとするはずです。しかし、アプリケーション開発者が再現したブラウザの挙動そっくりの挙動まではその機能を保とうとはしてくれません。もし将来、Webに新たな操作方法が追加され、`disabled` 属性のついている要素ではその操作に対するイベントが発火しない仕様になったとしたら、自身で「disabledな状態」を実装している場合には、そのイベントに対しても「disabledな状態」が適用されるよう、自分たちで追従していかなければなりません。

果たして、「disabledな状態」の要素にTabキーでフォーカスできないことは、そのリスクを犯してまで改善する必要があるものなのでしょうか？

### ARIA無しのほうが、悪いARIAよりも良い（No ARIA is better than Bad ARIA）

WAI-ARIAの属性を使用すること自体にも、注意するべき点があります。 **WAI-ARIAの属性は慎重に注意深く使用されるべきもの** です。

WAI-ARIA自体の解説やWAI-ARIAを利用した実装の例などを紹介する[ARIA Authoring Practices Guide (APG) ](https://www.w3.org/WAI/ARIA/apg/)の[Read Me First](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/)には、「No ARIA is better than Bad ARIA」として、WAI-ARIAを使用するうえでの注意点を書いています。

すこし古いものですが[^apg]、[ウェブアクセシビリティ基盤委員会が公開している日本語訳](https://waic.jp/translations/2019/NOTE-wai-aria-practices-1.1-20190207/#no_aria_better_bad_aria)より引用します。

[^apg]: 現在W3Cが公開している[ARIA Authoring Practices Guide (APG) ](https://www.w3.org/WAI/ARIA/apg/)は、以前は「WAI-ARIA Authoring Practices」というタイトルでした。引用している日本語訳は、その当時の文章を翻訳したものです。

> 原則2: ARIAは、パワーと危険を生み出すため、姿を消すこともでき、拡張することもできます。
>
> 情報の支援技術が必要とするユーザインタフェース要素の意味と目的は、アクセシビリティ・セマンティックスと言います。 支援技術の観点から、ARIAは、重要なアクセシビリティ・セマンティックを使って、作成者にHTMLやSVGの要素をドレスアップさせる能力を提供します。この重要なアクセシビリティ・セマンティックは、他の方法では、支援技術が、確実には引き出せないものです。
> 
> ARIAのいくつかは、コートに似ています。オリジナルのセマンティックやコンテンツを、隠したり、書き換えたりするためです。
>
>
> ```html
> <a role="menuitem">支援技術は、この部分をリンクでは無く、メニューのアイテムとして理解します。</a>
> <a aria-label="支援技術のユーザーは、「リンク・テキスト」では無く、このaria-labelの内容にだけ気づくことができます。">リンク・テキスト</a>
> ```
>      
> 一方で、ARIAのいくつかの用途は、サスペンダーかベルトに似ています。 オリジナル・コンテンツに不可欠なサポートを提供する意味を加えます。
> ```html
> <button aria-pressed="false">音を消す。</button>
> ```
>     
> これが、ARIAのパワーです。 支援技術が確実に解釈できる方法で、作成者は、ほぼどんなユーザインタフェースも記述できるようになります。
>
> これはまた、ARIAの危険な一面でもあります。 作者は、うっかり、アクセシビリティのセマンティックを書き換えることができます。
>
> ```html
> <table role="log">
>   <!--
>     支援技術のユーザーが、テーブルとして認識できないテーブルです。
>     Logのroleがブラウザに、これはテーブルでは無くログであることを、伝えます。
>   -->
> </table>
> <ul role="navigation">
>   <!-- これは、ナビゲーションの領域で、リストではありません。 -->
>   <li><a href="uri1">nav link 1</li>
>   <li><a href="uri2">nav link 2</li>
>   <!-- エラーです! この上のリストは、リンクではありません! -->
> </ul>
>
> [WAI-ARIA オーサリング・プラクティス 1.1](https://waic.jp/translations/2019/NOTE-wai-aria-practices-1.1-20190207/#no_aria_better_bad_aria)

上記の引用にはいくつかのコード例が出てきます。1つめのコード例では、リンク（`<a>` 要素）に  `role="menuitem"` を付けることでスクリーンリーダーのような支援技術に「ただのリンク」ではなく「メニューのアイテム」であることを認識させたり、`aria-label` 属性を使ってリンクのテキストを上書きして伝えたりしています。2つめのコード例では、ボタン（`<button>` 要素）に `aria-pressed` 属性を付けることで、このボタンがトグルボタン（「押されている・押されていない」の状態をもつボタン）であることを伝え、さらに属性値が `"false"` であることから「押されていない」すなわち「音を消していない」状態であることを伝えられています。

`role="menuitem"` や `aria-pressed` はHTMLの仕様の範囲では表現できない、WAI-ARIAの属性を使わなければ表現できないもので、これらの属性を使うのが妥当なシーンであれば良い活用例といえます。

3つめのコード例は明らかな悪い例として紹介されています。 テーブル（`<table>` 要素）に `role="log"` を付けると、支援技術がその部分をテーブルとして認識できなくなってしまいます。テーブルである以上、その内側には行と列による情報の配置があるでしょうが、スクリーンリーダーはこの部分をテーブルとしてユーザーに伝えなくなってしまい、ユーザーはその内部に配置されたセル（だったもの）の情報の意味を捉えられなくなる可能性があります[^screenreader]。リスト（`<ul>` 要素）に `role="navigation"`）をつけると、やはりリストではなくなってしまいます。内部に置かれたリスト項目（`<li>` 要素）をリスト項目としてスクリーンリーダーが読み上げなくなったり、リスト項目がいくつあるのかを伝えてくれる機能が使えなくなったりします[^link]。


[^screenreader]: 実際のスクリーンリーダーのような支援技術が、これらをどう解釈するかどうかは、ブラウザや支援技術の実装により異なるかもしれません。それ自体もまた、堅牢性（互換性）というアクセシビリティを構成する要素へネガティブな影響を与えます。
[^link]: 日本語版のコード例では「この上のリストは、リンクではありません」と書かれていますが、[現在公開されている文書](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/)では「Previous list items are not in a list!」つまり「この上のリスト項目は、リスト内にありません！」と書かれています。日本語版のコードでリンクの終了タグ（`</a>`）が抜けていたりするので、HTMLの文法ミスの指摘だったものが、WCAG 2.2で達成基準4.1.1が廃止されたことで変更されたのかもしれません。面倒くさいので変更履歴は追っていません。


また、1つめのコード例に出てくる `aria-label` 属性を使用してリンクのテキストを上書きしているものも、支援技術が認識するテキストと視覚的に表示されているテキストとの不一致を起こします。スクリーンリーダーを使用している弱視のユーザーを混乱させたり、スクリーンリーダーのユーザーとそうでないユーザーとのコミュニケーションに支障をきたすことが考えられます。

このように、WAI-ARIAの属性の使用は「パワーと危険を生み出す」ものなので、そのパワーは慎重に活用しなければなりません。そして「危険」が生まれているかどうかは、見た目からは判断できません。WAI-ARIAに熟知している人が関わっていたとしても、コードレビューや動作チェックをすり抜けて、誰かにとってのアクセシビリティを破壊してしまうかもしれません。

また、そもそもWAI-ARIAへの対応が、支援技術によりまちまちであることにも注意が必要です。[Accessibility Support (a11y-support.io)](https://a11ysupport.io/)には各種機能へのスクリーンリーダーの対応状況がまとめられていますが、すこしスクロールして眺めていけば「none」「partial」となっているものが多いことに気付けるはずです。WAI-ARIAの仕様にあるからといって、何も考えずに使うだけでアクセシビリティが向上するというものではないのです。

そして、[日本の視覚障害者に最も使われているスクリーンリーダー](https://jbict.net/survey/at-survey-03)である[PC-Talker](https://www.aok-net.com/screenreader/)の対応状況は、Accessibility Supportには掲載されていません。PC-Talkerで問題がないかどうかは、PC-Talkerや[クリエイター版 PC-Talker](https://www.aok-net.com/pctksdk.htm)などで確かめる必要があります。

スクリーンリーダー以外にも支援技術は存在しますし、支援技術として開発されていない便利ツールがたまたま支援技術のように機能している場合もあります。それらのすべてがWAI-ARIAの属性を解釈できるわけではありません。

WAI-ARIAの属性は非常に扱いが難しく、そして支援技術が解釈できる保証もありません。HTMLの仕様の範囲で表現できることは、WAI-ARIAの属性を使わずに表現されるべきです。

## フォーカスできないことが本当に問題なのかに目を向ける

そもそも、`disabled`属性ではなく`aria-disabled`属性を使うことを主張する人たちは、「disabled状態の要素にフォーカスできなくて困っているスクリーンリーダーのユーザー」を実際に見たことがあるのでしょうか？

もし、「disabled状態の要素にフォーカスできなくて困る」状態が実際のスクリーンリーダーのユーザーに起きているのであれば、`aria-disabled` 属性を使いdisabledな要素にフォーカスできるよう変更することは、大きな改善であると言えるでしょう。ユーザビリティテストとしてスクリーンリーダーのユーザーに操作してもらい、その画面を利用するうえでdisabled状態の要素の存在に気付けず、タスクを完了できないような状況は実際に考えられます。「その要素さえ知覚できれば良いのに」という状態であれば、ぜひ実施するべきです。

しかし、どうも「`disabled` 属性ではなく `aria-disabled` 属性を使うべき」という主張をしている記事では、実際に困っているスクリーンリーダーのユーザーの存在を感じられないのです（実際に困っているユーザーがいたのならすみません……）。

そしてそれよりも、そもそもdisabled状態の要素が、本当にdisabled状態である必要があるのか、Tabキーによるフォーカス移動で知覚できなければいけないものなのかも、目を向けるべき問題です。

ユーザーはずっとTabキーだけでページを読んでいるわけではありませんし、disabled状態のフォームを知覚しなくてもタスクが完了できるのであれば、それはそれで問題ないのかもしれません。

`disabled`属性が使われ、ユーザーが知覚できなくて困る状況として思いつくのは、たとえば入力フォームの最後にある送信ボタンが、必須項目の入力や入力規則を満たすまで、つまりエラーのある状態ではdisabled状態になって、押せなくなっているというものです。

入力フォームであれば、ユーザーはTabキーで移動してくる可能性は高いと思われ（スクリーンリーダーで、文字入力と読み上げカーソル移動を交互にやっていくのはかなり面倒くさいのです……）、送信ボタンを飛び越えて関係のない場所にフォーカスが移動したらたしかに困惑しそうです。そういったUIなのであれば、「押せない」状態のボタンにフォーカスできたほうが良いのかもしれません。

### 本当に、「スクリーンリーダーを使う人が知覚できない」ことだけの問題なのか？

とはいえ、以下のような可能性も考えるべきです。

- disabled状態の送信ボタンに辿りついても、なぜdisabled状態になっているのかわからない
- 入力エラーがどこかにあるかもしれないと思っても、どの入力欄で発生しているのかすぐにはわからない
- 上記のような問題が、実はスクリーンリーダーのユーザー以外にも発生している

こういう場合、「そもそもdisabled状態にするのが適切なんだろうか」というところにも目を向けるべきです。


- 送信ボタンに辿りついたときに、エラーが存在することを伝える方法はないだろうか
- 送信ボタンまで来る前に、入力中にエラーをユーザーにフィードバックする方法はないだろうか
- 送信ボタンをいつでも押せるようにして、ボタンを押したときにエラーメッセージをスクリーンリーダーでもわかるかたちで表示するほうが、エラーの存在に気付きやすいかもしれない

これにはいろいろな解があるはずで、「Webアプリケーションアクセシビリティ」にも使えそうなテクニックがいくつか紹介されています。いろいろな可能性を模索して、誰にとっても使いやすい状態を目指していくべきものだと思います。