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 で開き、各種スクリーンリーダーにて「ランドマーク間の移動」の操作を行い、ランドマークへの移動およびランドマーク名の読み上げが適切になされるかを検証しました。

検証に用いたスクリーンリーダー

「ランドマーク間の移動」操作の方法

検証結果

ランドマークを暗黙的に実装した検証用デモに対し、各種スクリーンリーダーで「ランドマーク間の移動」を行った結果、以下のテーブルのとおりの結果になりました。各データセルには、日本語音声合成による実際の読み上げ内容を記載しています。一部、「N/A」と記載されたセルがありますが、これはランドマークへの移動およびランドマーク名の読み上げがなされなかったことを示しています。

ランドマーク要素PC-Talker Neo (Windows 10) w/ Chrome, Edge, FirefoxNVDA 2021.2jp (Windows 10) w/ Chrome, Edge, FirefoxNarrator (Windows 10) w/ Chrome, Edge, FirefoxVoiceOver (macOS 11.6 Big Sur) w/ Safari, ChromeVoiceOver (iOS 15.1) w/ Safari, ChromeTalkBack 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/AN/AN/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」となっていますが、以下の理由から、実用上は深刻度の高い問題ではないかもしれません。

ちなみに、ランドマークを冗長に実装したデモも併せて用意し、同じ操作によって比較検証しましたが、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 属性を併記する意義は、なくなってきたのかなという気がします。