WAI-ARIA ランドマークを暗黙的に実装する
この記事は、アクセシビリティ Advent Calendar 2021 の13日目の記事です。
ウェブアクセシビリティを高めるための実装方法のひとつに、WAI-ARIA があります。
WAI-ARIA とは、Web Accessibility Initiative (W3C の中で、ウェブアクセシビリティに関する仕様を検討する部会) が策定した、Accessible (アクセシブル) な Rich Internet Applications (リッチインターネットアプリケーション : RIA) に関する仕様です。WAI-ARIA によって、ユーザーインターフェースオブジェクトの「Roles (役割)」「States (状態)」「Properties (特性)」を動的にスクリーンリーダーなどの支援技術に伝達することができますが、このうち「Roles」には、ウェブページ内のランドマークをセマンティックに明示するための Landmark Roles という仕様があり、以下の8つが定義されています。(参考 : WAI-ARIA 1.1 §5.3.4 Landmark Roles)
- banner
- サイトの各ページに共通して存在する、特定のサイトである旨を表現する領域。(例 : サイト名称やロゴマークを含むサイト共通ヘッダー)
- navigation
- ナビゲーションの領域。(例 : グローバルナビゲーション、ローカルナビゲーション、ビッグフッターのサイトマップリンク、など)
- search
- 検索機能の領域。(例 : サイト内検索)
- main
- ページ内のメインコンテンツの領域。(ヘッダー、フッター、ナビゲーションではない、いわば「本文」エリア)
- region
- 情報設計上の意図に基づいて、ユーザーがナビゲートしやすいよう定義された特定の領域。(例 : 本文のサマリー、重要な情報や機能、など)
- form
- ユーザーが情報を入力するための、フォームの領域。
- complementary
- メインコンテンツとは別に用意される、補足的な情報群の領域。(例 : 関連情報へのリンク、メインコンテンツに直接関係しないウィジェット類、広告、など)
- contentinfo
- 親ドキュメント (サイト) に関することを含む、コンテンツに付帯する各種情報の領域。(例 : コピーライト表記、プライバシーポリシーやアクセシビリティポリシーへのリンク、などを含むサイト共通フッター)
これらは、HTML 要素の中に role 属性として記述しますが (たとえば、検索フォームであれば <form role="search">
という具合)、現在は role="search"
以外のランドマークは HTML のセマンティクスとしてあらかじめ用意されていて、たとえば、ナビゲーション領域であることを示す HTML の <nav>
要素は暗黙的に role="navigation"
であると仕様上定義されているので、<nav role="navigation">
と冗長に記述しなくてもよいことになっています。(参考 : WAI-ARIA Authoring Practices 1.1 §4.3 Landmark Roles の、各ランドマークの「HTML Techniques」の項)
ところが日本においては、シェアがもっとも大きいスクリーンリーダーである PC-Talker が、HTML 要素に含まれる暗黙的なランドマークを解釈できていなかったという事情があり、(少なくとも数年前は) <nav role="navigation">
のように role 属性を併記することが無難であるとされていたように思います。個人的には、そろそろ、こうした冗長な記述は止められないものだろうか、という思いがあり (というのも、W3C 勧告 ARIA in HTML には誤用例として「Don't add redundant roles」が挙げられていますし、Nu Html Checker でもバリデーション結果が「Warning」になるからです)、今回改めて、冗長ではない暗黙的なランドマーク実装を施したウェブページを、PC-Talker をはじめとする現行の各種スクリーンリーダーで使用してみて、実用上問題がないかどうかを、検証してみることにしました。
検証内容
CodePen で、ランドマークを暗黙的に実装した検証用デモを用意しました。
See the Pen WAI-ARIA ランドマークを暗黙的に実装 (HTML 要素のみで、同じセマンティクスの role 属性は併記しない) by @caztcha (@caztcha) on CodePen.
これを Full Page View で開き、各種スクリーンリーダーにて「ランドマーク間の移動」の操作を行い、ランドマークへの移動およびランドマーク名の読み上げが適切になされるかを検証しました。
検証に用いたスクリーンリーダー
- Windows 10 (併用ブラウザ : Chrome、Edge、Firefox)
- PC-Talker Neo クリエーター版 (Version 2111)
- NVDA (2021.2jp)
- ナレーター
- macOS 11.6 Big Sur (併用ブラウザ : Safari、Chrome)
- VoiceOver
- iOS 15.1 (併用ブラウザ : Safari、Chrome)
- VoiceOver
- Android 8.0 (併用ブラウザ : Chrome)
- TalkBack 12.1
「ランドマーク間の移動」操作の方法
- PC-Talker Neo、NVDA、ナレーター (Windows 10) では、[D] キー (または [Shift]+[D] キー) でランドマーク間を移動できます。
- VoiceOver (macOS) では、「Web ローター」で「ランドマーク」を選択したうえで、上下矢印キーでランドマーク間を移動できます。
- VoiceOver (iOS) では、「ローター」で「ランドマーク」を選択したうえで、上下方向のフリックでランドマーク間を移動できます。
- TalkBack (Android) では、上下往復スワイプで「ランドマーク」を選択したうえで、上下方向のフリックでランドマーク間を移動できます。
検証結果
ランドマークを暗黙的に実装した検証用デモに対し、各種スクリーンリーダーで「ランドマーク間の移動」を行った結果、以下のテーブルのとおりの結果になりました。各データセルには、日本語音声合成による実際の読み上げ内容を記載しています。一部、「N/A」と記載されたセルがありますが、これはランドマークへの移動およびランドマーク名の読み上げがなされなかったことを示しています。
ランドマーク要素 | PC-Talker Neo (Windows 10) w/ Chrome, Edge, Firefox | NVDA 2021.2jp (Windows 10) w/ Chrome, Edge, Firefox | Narrator (Windows 10) w/ Chrome, Edge, Firefox | VoiceOver (macOS 11.6 Big Sur) w/ Safari, Chrome | VoiceOver (iOS 15.1) w/ Safari, Chrome | TalkBack 12.1 (Android 8.0) w/ Chrome |
---|---|---|---|---|---|---|
<header> | バナーランドマーク | バナーランドマーク | バナーのランドマーク | バナー内 (Chrome では N/A) | バナーランドマーク | N/A |
<nav> | ナビゲーションランドマーク | ナビゲーションランドマーク | ナビゲーションのランドマーク | ナビゲーション内 | ナビゲーションランドマーク | ナビゲーション |
<main> | メインランドマーク | メインランドマーク | メインのランドマーク | メイン内 (Chrome では「本文内」) | メインランドマーク | 本文 |
<section> | N/A | 領域 | 領域のランドマーク | 領域 (Chrome では N/A) | 領域ランドマーク | 地域 |
<form> | N/A | フォーム | フォームのランドマーク (Chrome、Firefox では N/A) | N/A | N/A | N/A |
<aside> | 補足ランドマーク | 補足情報ランドマーク | 補助のランドマーク | 補足内 | 補足ランドマーク | 補足 |
<footer> | コンテンツ情報ランドマーク | コンテンツ情報ランドマーク | コンテンツ情報のランドマーク | コンテンツ情報内 (Chrome では N/A) | コンテンツ情報ランドマーク | N/A |
考察
ナビゲーション (<nav>
)、メインコンテンツ (<main>
)、補足的な情報群の領域 (<aside>
) は、PC-Talker をはじめ、どのスクリーンリーダーでも利用可能になっています。一部のユーザーエージェント (ブラウザとスクリーンリーダーの組み合わせ) で、<header>
(暗黙的な role="banner"
)、<section>
(暗黙的な role="region"
)、<form>
(暗黙的な role="form"
)、<footer>
(暗黙的な role="contentinfo"
) への対応が「N/A」となっていますが、以下の理由から、実用上は深刻度の高い問題ではないかもしれません。
- ヘッダー (サイト名称やロゴマークなど) やフッター (コピーライト表記など) への「ランドマーク間の移動」でのアクセスは、相対的にニーズが低そう。もしヘッダーやフッターの中に、ナビゲーション機能が含まれていれば、その部分は
<nav>
でマークアップすることで解決できる。 - 重要な特定の領域 (
<section>
) には情報構造として適切な見出し要素が存在するべきであり、であれば、スクリーンリーダーに用意されている慣習的な別手段 ([H] キーを押すなど) によってショートカット的なアクセスが可能である。 - フォームコントロール (入力フィールド) へは、スクリーンリーダーに用意されている慣習的な別手段 ([F] キーを押すなど) によってショートカット的なアクセスが可能である。
ちなみに、ランドマークを冗長に実装したデモも併せて用意し、同じ操作によって比較検証しましたが、PC-Talker、NVDA、ナレーター、iOS VoiceOver、macOS VoiceOver (w/Safari) では、特に挙動の違いは見られませんでした。macOS VoiceOver (w/Chrome) および Android TalkBack では、冗長なランドマーク実装によって <header role="banner">
と <footer role="contentinfo">
が追加的に読み上げられるようになりましたが、macOS VoiceOver (w/Chrome) の場合、他のランドマークも含めてすべて「{英語の role 属性値}, うち」と読み上げられる形になってしまい、つまり、暗黙的な実装であれば「ナビゲーション内 (ない)」と素直に読み上げられていたところ、冗長な実装だと「navigation うち」と変に読み上げられるようになってしまい、かえってユーザーの認知負荷を高めてしまうように感じました。
当初懸案とされていた PC-Talker のランドマークのサポートという観点では、現行版の PC-Talker Neo であれば暗黙的なランドマークでも十分実用的である (かつ、冗長なランドマーク実装で特に挙動の改善が見られるわけではない) こと、また、macOS VoiceOver (w/Chrome) では冗長なランドマーク実装だとかえって日本語での読み上げが変になってしまうこと、を勘案すると、もはや日本においても、ランドマークのセマンティクスをあらかじめ持つ HTML 要素の中に同じセマンティクスの role 属性を併記する意義は、なくなってきたのかなという気がします。