集計ボタンを押したあとに画面が変わらないと、処理中なのか、押せなかったのかを判断できません。件数だけが書き換わる画面では、読み上げを使う人にも変化が伝わるようにします。
role="status"は、処理の進み具合や結果のような状態を知らせる領域です。MDNでは読み上げを待って知らせるaria-live="polite"と、領域全体を対象にするaria-atomic="true"が暗黙に適用されると説明されています。通知のために、毎回フォーカスを結果欄へ飛ばす必要はありません。
状態を出す領域を先に置く
状態の要素は最初からHTMLに置き、その中の文字を後で変えます。処理が終わる瞬間に領域ごと作ると、支援技術が変更を認識するタイミングにも注意が必要になるためです。
<button id="count-button" type="button">練習データを集計する</button>
<p id="count-status" role="status" aria-atomic="true"></p>
<script>
const button = document.getElementById('count-button');
const status = document.getElementById('count-status');
async function previewCount() {
if (button.disabled) return;
button.disabled = true;
status.textContent = '練習データを集計中です。';
try {
const rows = await new Promise(resolve => {
setTimeout(() => resolve([100, 200, 300]), 500);
});
const total = rows.reduce((sum, value) => sum + value, 0);
status.textContent = rows.length + '件の集計が完了しました。合計は'
+ total + 'です。保存はしていません。';
} catch (error) {
status.textContent = '集計結果を確認できません。入力と処理ログを確認してください。';
} finally {
button.disabled = false;
}
}
button.addEventListener('click', previewCount);
</script>
3件の数値と500ミリ秒の待ち時間は、画面を試すための架空の設定です。外部APIやGoogleスプレッドシートから取得しているわけではありません。期待する表示は3件、合計600、保存していないという内容です。待機の数字を実際の処理時間として使わないでください。
操作の状態と処理結果をそろえる
例では処理中のボタンを無効にし、終了したら再度使える状態へ戻します。文字だけを「完了」と変えても、ボタンが押せないままなら利用者は次へ進めません。成功した場合だけでなく、失敗した場合にも操作が戻るかを確かめます。
ただし、ボタンの無効化は同じ画面での連打を抑えるものです。別のタブや再読込、通信後の再試行による二重処理まで防ぐ機能ではありません。保存や送信を加える場合は、サーバー側でも同じ依頼を識別し、処理済みかを確認する仕組みが必要になります。
途中経過を細かく読み上げすぎない
1行読むごとに件数を変えると、読み上げが何度も続いて操作の説明を聞きづらくなる場合があります。開始、区切りの進捗、完了など、利用者が判断に使う変化を選びます。すぐ終わる処理なら、結果だけを伝える設計も考えられます。
通常の完了報告へassertiveを使うと、読み上げ中の内容を割り込んで知らせることがあります。急いで対処が必要な通知かを判断し、状態表示を目立たせたいという理由だけで通知の強さを上げないようにします。
実際の利用条件で確かめる
ブラウザでは、押した直後の処理中表示、完了の件数、ボタンが戻ることを確認します。続けてもう一度押しても、同じ流れになるかを試してください。エラー表示も必要な画面なら、失敗を発生させる練習用条件を別に作ります。
DOMの文字が変わることと、音声がどう聞こえるかは別の確認です。この例はブラウザ内の状態変化を確認するもので、スクリーンリーダーの音声を検証した結果ではありません。利用するブラウザと支援技術で、説明が途中で切れないか、必要以上に繰り返されないかを確かめます。
