「データがありません」をどう見せるか:Empty Stateのマークアップとアクセシビリティの作法
フロントエンド開発の現場で、意外と頭を悩ませるのが「リストが空の時」のUIです。
「とりあえず `display: none` で消しておけばいいや」「`v-if` で非表示にして終わり」……そんな風に済ませていませんか? もちろん、表示上の見た目はそれで解決します。しかし、「何もない」という状態をユーザーにどう伝えるか、そして支援技術(スクリーンリーダー)に対してどう振る舞わせるかは、プロダクトの品格を左右する重要な分岐点です。
今日は、中級エンジニアなら押さえておきたい、Empty State(空の状態)のセマンティックなマークアップと、`aria-live` を活用した動的通知のベストプラクティスについて深掘りします。
—
1. なぜ「空のリスト」をマークアップする必要があるのか
リストが空になったとき、ブラウザは当然ながら `ul` や `ol` の中身を空っぽとしてレンダリングします。しかし、アクセシビリティの観点からは、「リストが空であること」を明示的に伝える必要があります。
もし単に要素を消してしまったら、スクリーンリーダーのユーザーは「リストが消えたことに気づくのか? それとも単にロードに失敗したのか?」と迷子になってしまいます。
現場のベストプラクティスとしては、以下の2つのアプローチを使い分けます。
1. コンテナ自体を消す(DOMから削除): 構造的に意味がない場合。
2. Empty Stateを表示する: ユーザーに対して次のアクションを促す場合。
今回は後者の「Empty Stateの表示」にフォーカスします。
—
2. 実践的サンプル:`aria-live` を使ったUI構築
リストの中身が動的に変わるアプリケーション(検索画面やタスク管理など)では、リストが空になった瞬間、その旨をスクリーンリーダーに通知する必要があります。ここで登場するのが `aria-live` 属性です。
以下のコードは、実務でそのまま使える、アクセシブルなEmpty Stateの構成例です。
現在、表示するアイテムはありません。
3. ブラウザが裏側でやっていること:`aria-live` の挙動
`aria-live` は、ブラウザのアクセシビリティツリーに対して「この要素の変化を監視せよ」という命令を送ります。
- `polite` (おすすめ): ユーザーが現在行っている操作を邪魔せず、それが終わったタイミングで変更を読み上げます。リストの空状態通知にはこれが最適です。
- `assertive`: ユーザーの操作を割り込んででも即座に読み上げさせます。エラーメッセージや緊急の通知以外では、ユーザー体験を損なうため避けるべきです。
ブラウザのレンダリングエンジンは、`aria-live` が指定された要素内のDOM変化を検知すると、OS側のアクセシビリティAPIに対して「変更があった」というイベントを投げます。これにより、視覚的に見ていないユーザーにも「リストが空になった」という情報が確実に伝わります。
—
4. 現場のシニアからのアドバイス:UI設計の泥臭い注意点
コードを書くとき、以下の3点を意識するだけで、あなたの実装は一段階上のレベルへ到達します。
1. 「何もない」ことを責めない: 「結果が見つかりませんでした」という事務的な文言だけでなく、「条件を変えて検索してください」といった、ユーザーが次に進めるためのアクション(ボタンやリンク)を必ずセットで配置しましょう。
2. `ul:empty` 疑似クラスの罠: CSSの `:empty` は、改行やスペースすら入っていると反応しません。マークアップする際は、`
` と一行で書くか、JSで完全にDOMを制御するようにしてください。
3. Loadingとの兼ね合い: 「空の状態」と「読み込み中」を混同させないこと。読み込み中は `aria-busy=”true”` を活用し、空の状態とは別のセマンティクスを割り当てるのがプロの仕事です。
—
まとめ
Empty Stateは、単なる「寂しい画面」ではありません。ユーザーとの対話が途切れないための重要なUIコンポーネントです。
- リストが空なら、空であることを示すマークアップを出す。
- `aria-live=”polite”` で、スクリーンリーダーに優しく状況を伝える。
- 「次に行うべきこと」を添えて、ユーザーを迷わせない。
この細部へのこだわりこそが、あなたの作るプロダクトを「ただ動くもの」から「信頼されるもの」へと変えていきます。明日のコードから、ぜひ意識してみてください。応援しています。

コメント