通常、スクリーンリーダーはフォーカスされた要素または独自のコマンドを使用するときにだけコンテンツを読み上げます。動的に挿入・変更されたコンテンツを支援技術が知ることはできず、変更されたことがわかるのは視覚情報のあるユーザーだけです。
組み込みバリデーションのフォーム入力エラーは、フォーカスされたフィールドに表示されるためアクセシビリティの配慮は不要ですが、独自バリデーションを追加する場合はアクセシビリティの配慮が必要です。
フォームの入力エラーでアクセシビリティに考慮が必要になるケース
組み込みのバリデーションチェックでフォームの入力値を検証する場合 ※不要
組み込みのバリデーションチェックを利用して、フォームの入力値の検証を行う場合、送信ボタンを押下した時に、バリデーションチェックが走ります。そして、入力エラーのある入力フィールドにフォーカスが行き、スクリーンリーダーは、エラーメッセージを読み上げてくれます。そのため、特別にアクセシビリティを考慮しなくても良いと思われます。
独自のバリデーションチェックでフォームの入力値を検証する場合 ※必要
組み込みのバリデーションチェックを使わず、例えば送信ボタン押下時以外にバリデーションチェックする場合や独自のバリデーションチェックを実装する場合は、動的な要素の変更を支援技術に伝えることができません。そのため、アクセシビリティを考慮した実装が必要になります。
実装方法
動的に変更される要素に、role=”alert” または aria-live=”assertive”を追加します。
ブラウザがroleをサポートしていない場合は、両方の属性を使っても良いです。ただし、role=”alert” と aria-live=”assertive” の両方を追加するとiOSのVoiceOverで二重に読み上げられるという問題があるそうなので、この点については留意しておく必要があります。
aria-live=”assertive”は、緊急性の高いステータスエラーなどにのみ使うべきとの声がありますが、Googleフォームを調べてみたところ、role=”alert” が使われていました。ここではrole=”alert”および、role=”alert”と等しいaria-live=”assertive” を使用した実装を紹介しています。(role=”alert”の使用は、要素が aria-live="assertive"
を持っていることを意味します。)
<div role="alert" aria-live="assertive"></div>
実装のポイント
- 変更される要素にrole属性とWAI-ARIAのaria-live属性を指定する
- role属性とWAI-ARIAのaria-live属性は、変更が起こる前に追加されている必要がある
- 属性は最初からHTMLに含めても、JavaScriptなどで動的に追加しても良い
- ライブリージョンには、フォーカスを当てずに、テキストの読み上げだけを行う
下記の例では、JavaScriptでエラーメッセージのテキストを切り替えています。その要素に対して、CSSやHTML、属性の変更があればキャッチしてくれますので、実装方法は別の方法でも問題ありません。
<div>
<label for="user_name">お名前<span class="required text-red-500 mx-1" aria-hidden="true">*</span></label>
<input type="text" name="user_name" id="user_name" autocomplete="username" placeholder="山田 太郎" required>
<span id="js-name-error" role="alert" aria-live="assertive" class="error-message" aria-hidden="true"></span>
</div>
const nameInput = document.getElementById('user_name');
const nameErrorMessage = document.getElementById('js-name-error');
const maxLength = 15;
nameInput.addEventListener("blur", () => {
if(nameInput.value.length > maxLength){
name.setAttribute("aria-hidden", "false");
nameErrorMessage.textContent = `お名前は、${maxLength}文字以内にしてください`;
}else{
name.setAttribute("aria-hidden", "true");
nameErrorMessage.textContent = "";
}
});
role属性とaria-live属性について
role属性(alertとstatus)
role=”status”かrole=”alert”を追加すると、スクリーンリーダーなどの支援技術が、その要素が更新されたかどうかを監視してくれるようになります。
statusとalertの違い
alertはスクリーンリーダーがなにかを読み上げている途中でも割り込みます。逆にstatusは、スクリーンリーダーが読み上げを終わるまで待ちます。
role | 通知タイミング | 使い所 | 暗黙的な値 |
alert | 即時。スクリーンリーダが読み上げているコンテンツがあっても、割り込みます。 | ユーザーに即座に伝えるべき、重要かもしれないメッセージを伝えるときに使用します。 | role=”alert”を持っている要素は、暗黙的に、ara-liveの値は、”assertive”を持っています。aria-atomicの値は、trueを持っています。 |
status | 現状読み上げているコンテンツを読み上げ終わった後、アイドル状態になったときに通知します。 | alertを正当化するほど重要ではなく、ステータスバーとして提示される必要のないものに使用します。 | role=”status”を持っている要素は、暗黙的に、ara-liveの値は、”polite”を持っています。aria-atomicの値は、trueを持っています。 |
aria-live属性
設定には off、polite、assertive があり、デフォルトはoffです。role属性をサポートしていないブラウザがあるため、この属性を併用して使うことがあります。
aria-liveはライブリージョン(ライブ領域)とも呼ばれています。
ライブリージョンは、ユーザーのフォーカスが別の場所にあるときに、フォーカスの外側で更新される領域のことです。ユーザーのフォーカスしている要素以外つまりフォーカスの外側で変更されるため、スクリーンリーダーなどの支援技術は、その変更に気づきません。role属性やaria-live属性を要素に追加すると、例えばフォームのバリデーションのエラーメッセージなど動的に変更された内容を、支援技術に知らせることができるようになります。
alia-live属性は、通知をするタイミングを変更・設定することができます。スクリーンリーダーの場合だと、即座に読み上げたり、アイドル状態になってから読み上げたりといった調整ができます。
※aria-live=”polite”はrole=”status”と等しく、aria-live=”assertive”はrole=”alert”と等しいです。
aria-live | 通知タイミング | 使い所 |
polite | アイドル状態のとき。スクリーンリーダーの場合は、現在読み上げているものが終わったタイミングで、読み上げます。 | alertを使うほど緊急で重要ではない場合に使用するのに適しています。aria-liveの使用の大部分を占めています。 |
assertive | 即時。スクリーンリーダーの場合は、その時に読み上げているものがあっても、割り込んで読み上げます。 | 「サーバーエラーが発生しました。ページを更新してください。」といったステータスメッセージなどの重要で緊急の更新にのみ使用するのが適切です。 |
off | デフォルトのため、明示的に指定する必要はありません。 | role=”alert” を持つ要素からの出力を止めたい場合などに使います。 |
おわりに
以上、動的なフォームのエラーメッセージを、ユーザーに通知する方法をご紹介しました。アクセシビリティに考慮したフォームの実装の参考になれば幸いです。