インライン要素を「ただの器」で終わらせない:ARIA Liveで実現する動的UIのアクセシビリティ
フロントエンド開発の現場で、ふと立ち止まる瞬間はないだろうか。「``や``で囲んだテキストをJSで書き換えたとき、スクリーンリーダーを使っているユーザーには、どう伝わっているんだろう?」と。
多くのエンジニアは、DOMを操作して終わりにしてしまう。しかし、本当に優れたUXを追求するなら、その更新が「ユーザーにとって意味のある変化」である以上、ブラウザの向こう側にいるユーザーにも確実に届ける責任がある。
今回は、インライン要素(`span`, `time`など)内の動的コンテンツを、アクセシブルに通知するための`aria-live`戦略について、現場の泥臭い知見を交えて解説する。
—
なぜ「更新」が伝わらないのか?
スクリーンリーダーは、基本的には「ページロード時」や「フォーカス移動時」の情報を読み上げる。DOMの一部(例えば残り時間のカウントダウンや、非同期で取得したステータス)が書き換わったとしても、スクリーンリーダーはそれを無視することが多い。なぜなら、無闇に全ての変更を読み上げると、ユーザーの体験がノイズまみれになるからだ。
ここで登場するのが `aria-live` 属性だ。これを使うことで、我々開発者はブラウザに対して「この要素の中身が変わったら、ユーザーに伝えてくれ」と指示を出せるようになる。
aria-liveの「重さ」を理解する
`aria-live` には主に3つのレベルがある。
- `off`(デフォルト):通知しない。
- `polite`:ユーザーが操作を終えたタイミングで読み上げる。基本はこれ。
- `assertive`:割り込んで即座に読み上げる。エラーメッセージなど、緊急性の高いものに限定すべき。
これをインライン要素に付与する際、最も注意すべきなのが「更新の範囲」だ。
—
実践:time要素のカウントダウンを正しく伝える
例えば、オークションの残り時間表示。`time` 要素の中身が1秒ごとに書き換わるようなUIを想像してほしい。これをそのまま `aria-live=”polite”` にすると、毎秒読み上げが発生して地獄のような体験になる。
ここで `aria-atomic` の出番だ。
aria-atomic:情報の「塊」を定義する
`aria-atomic` は、更新された箇所だけを読み上げるか、それとも要素全体を読み上げるかを制御する。「残り時間 00:05」という表示で「5」だけが更新されたときに「5」とだけ読まれても意味がわからない。`aria-atomic=”true”` を指定することで、「残り時間 00:05」という塊ごと読み上げさせるのが正解だ。
終了まで残り:
---
現場で陥りやすい「罠」
シニアレベルとして、後輩に必ず伝えている注意点が2つある。
1. `aria-live` は「空の要素」に後付けしてはいけない
DOM構築時に最初から `aria-live` 属性が存在していない要素に対して、後からJSで属性を付与しても、多くのブラウザ(特にモバイル環境)ではうまく動かないことがある。必ずHTMLの初期状態で記述しておくか、あるいは `aria-live` を設定したラッパー要素の中に動的コンテンツを流し込むようにしよう。
2. 「Live Region」は慎重に使う
すべての動的テキストに `aria-live` を入れるのは間違いだ。ユーザーが今、何に注目しているかを想像してほしい。メニューの開閉や、フォームのバリデーションエラーなど、「ユーザーの行動に対するフィードバック」として必要な時だけ使うのが、プロの引き出しというものだ。
---
まとめ:アクセシビリティは「配慮」という名の設計
フロントエンドのUIは、画面上の画素を操作するだけではない。スクリーンリーダーという「もう一つのブラウザ」を通して、情報の意味を届ける作業だ。
- `aria-live="polite"` で読み上げのタイミングを制御する。
- `aria-atomic="true"` で情報の文脈を保つ。
- 頻度を考慮する(毎秒の更新は避ける)。
この3点を守るだけで、あなたのUIは多くの人にとって「使えるもの」から「使いやすいもの」へと進化する。技術は、誰かを排除するためにあるのではなく、誰かを取りこぼさないためにある。ぜひ、次のプルリクからこの視点を取り入れてみてほしい。

コメント