ARIAとは?

ARIA(Accessible Rich Internet Applications)は、リッチなWebアプリケーションと動的コンポーネントのアクセシビリティを向上させることができるW3C仕様です。ARIA (Accessible Rich Internet Applications)

🏷️ 役割

要素が何であるかを定義(ボタン、ナビゲーション、アラートなど)

role="button"

📊 状態

要素の現在の状態を記述(チェック済み、展開済み、無効など)

aria-expanded="true"

🔧 プロパティ

追加情報を提供(ラベル、describedby、コントロールなど)

aria-label="メインメニュー"

⚠️ ARIAのゴールデンルール

ネイティブHTMLを使用できる場合はARIAを使用しない

ARIA属性を使用したフォーム

悪い例

ARIAなしのフォーム

❌ 適切なARIA属性がないアクセシブルでないフォーム:

<!-- 悪い例:ラベルなし、説明なし -->
<input type="text" placeholder="あなたのメール">

<!-- 悪い例:アイコンがアクセシブルでない -->
<button>
  <span class="icon">🔍</span>
</button>

<!-- 悪い例:エラーが関連付けられていない、オートコンプリートなし -->
<input type="password">
<div class="error">パスワードが短すぎます</div>
パスワードが短すぎます
同意します 利用規約

良い例

ARIAを使用したフォーム

✅ 適切なARIA属性を使用したアクセシブルなフォーム:

<!-- 良い例:可視ラベルのないフィールドのaria-label -->
<input
  type="text"
  aria-label="メールアドレス(必須)"
  aria-describedby="email-desc"
  aria-required="true">
<span id="email-desc">形式:name@example.com</span>

<!-- 良い例:aria-labelを持つボタン -->
<button aria-label="フォームを送信">
  <span aria-hidden="true">🔍</span>
</button>

<!-- 良い例:aria-describedbyで関連付けられたエラー -->
<input
  type="password"
  aria-label="パスワード(8文字以上)"
  aria-invalid="true"
  aria-describedby="pwd-error"
  autocomplete="new-password">
<div id="pwd-error" role="alert">
  パスワードは8文字以上である必要があります
</div>
形式:name@example.com
数字と文字を含む8文字以上
通知オプション
重要な更新をメールで受け取る
緊急アラートをSMSで受け取る
使用されるARIA属性:
  • aria-label:アクセシブルなラベルを提供
  • aria-describedby:詳細な説明を関連付ける
  • aria-required:必須フィールドを示す
  • aria-invalid:無効なフィールドを通知
  • aria-labelledby:既存のラベルを参照
  • role="alert":エラーをすぐにアナウンス
  • aria-hidden:装飾的要素を非表示
  • aria-live:動的変更をアナウンス

説明: ARIA属性は、支援技術にラベル、説明、状態を提供することでフォームを豊かにします。

アクセシブルなアコーディオン

悪い例

ARIA属性なし

Webアクセシビリティとは何ですか?+
なぜ重要なのですか?+
どのように始めればよいですか?+
<!-- 悪い例:ARIA属性なし、キーボードナビゲーションなし -->
<div class="accordion-header" @click="toggle">
  <span>Title</span>
  <span>+</span>
</div>
<div v-if="open">
  Content
</div>

良い例

適切なARIAを使用

<!-- 良い例:キーボードナビゲーション付きの完全なARIA -->
<button
  id="accordion-button-1"
  aria-expanded="false"
  aria-controls="panel-1"
  @click="toggle"
  @keydown.enter="toggle"
>
  Title
</button>
<div
  id="panel-1"
  role="region"
  aria-labelledby="accordion-button-1"
  :hidden="!open"
>
  Content
</div>

説明: アコーディオンは、適切なARIA属性を使用し、キーボードナビゲーションをサポートし、状態の変更をアナウンスする必要があります。

Tabindexとキーボードナビゲーション

tabindex属性は、要素がキーボードフォーカスを受け取ることができるかどうか、どの順序で受け取るかを制御します。

✅ tabindex="0"

要素は自然なDOM順序でフォーカス可能

tabindex="0"
<!-- 良い例:インタラクティブ要素がフォーカス可能 -->
<div role="button" aria-label="Custom action" tabindex="0">
  Custom button
</div>

⚠️ tabindex="-1"

JavaScriptでフォーカス可能だがTabではない

tabindex="-1"
<!-- 良い例:プログラム的フォーカス用 -->
<div role="alert" aria-live="assertive" tabindex="-1">
  Error message
</div>

❌ tabindex > 0

ナビゲーション順序を変更(避けるべき!)

tabindex="5"
<!-- 悪い例:自然なタブ順序を壊す -->
<button tabindex="3">Third</button>
<button tabindex="1">First</button>
<button tabindex="2">Second</button>

📋 Tabindexのベストプラクティス

  • カスタムインタラクティブ要素をフォーカス可能にするにはtabindex="0"を使用
  • プログラム的フォーカス(モーダル、アラート)にはtabindex="-1"を使用
  • 正の値は絶対に使用しない - DOM順序を尊重する
  • ネイティブなインタラクティブ要素(<button><a><input>)はtabindexを必要としない

🎯 インタラクティブな例

これらの要素でキーボードナビゲーション(Tab/Shift+Tab)をテストします:

✅ フォーカス可能な要素

リンク
カスタムボタン(div)

❌ フォーカス不可能な要素

シンプルなテキスト(div)
インラインテキスト(span)

段落

💡 テストのヒント

  • Tabを使用して前方にナビゲート
  • Shift + Tabを使用して後方にナビゲート
  • SpaceまたはEnterを使用して要素を有効化
  • フォーカスインジケーター(青いアウトライン)を観察
  • どの要素がフォーカスを受け取れるか、受け取れないかに注意

アクセシブルなドロップダウンメニュー

悪い例

良い例

説明: ドロップダウンメニューは、キーボードナビゲーションをサポートし、Escapeで閉じ、適切にフォーカスを維持する必要があります。

アクセシブルな画像ギャラリー

悪い例

良い例

説明: 画像ギャラリーは、キーボードナビゲーションを許可し、各画像にコンテキスト説明を提供する必要があります。ARIA tablist/tab/tabpanelパターンは、この使用例に最適です。

アクセシブルなソート可能なテーブル

悪い例

名前 ↑メール 役割 ステータス
アリス・マーティンalice@example.com管理者アクティブ
ダイアナ・モローdiana@example.comユーザー停止中
チャーリー・ルロイcharlie@example.comモデレーターアクティブ
ボブ・デュポンbob@example.comユーザー非アクティブ

良い例

アリス・マーティンalice@example.com管理者アクティブ
ダイアナ・モローdiana@example.comユーザー停止中
チャーリー・ルロイcharlie@example.comモデレーターアクティブ
ボブ・デュポンbob@example.comユーザー非アクティブ
列ヘッダーをクリックしてテーブルをソートします。Tabを使用してソートボタン間をナビゲートします。

説明: ソート可能なテーブルは、現在のソート状態を示し、キーボードナビゲーションを許可し、スクリーンリーダーに変更をアナウンスする必要があります。

動的なaria-live領域

悪い例

aria-liveなし

変更がアナウンスされない

<!-- Mauvais : pas d'attribut aria-live -->
<div class="status-banner">
  <p></p>
</div>

カウンター:0

問題点:

  • 変更がアナウンスされない
  • スクリーンリーダーユーザーはコンテンツが変更されたことを知らない
  • メッセージの重要度の指示がない

良い例

適切なaria-liveを使用

変更が優先度に応じてアナウンスされる

<!-- Bon : avec aria-live="polite" pour informations -->
<div
  class="status-banner"
  aria-live="polite"
  aria-atomic="true"
  role="status"
>
  <p>Information : Données mises à jour</p>
</div>

<!-- Bon : avec aria-live="assertive" pour alertes -->
<div
  class="alert-banner"
  aria-live="assertive"
  aria-atomic="true"
  role="alert"
>
  <p>Attention : Action requise immédiatement</p>
</div>

Politeゾーン(情報)

利点:

  • 重要なメッセージはaria-live="assertive"で中断
  • 情報メッセージはaria-live="polite"で待機
  • aria-atomic="true"は領域コンテンツ全体をアナウンス
  • 適切な役割(status、alert)がより多くのコンテキストを提供

説明: Aria-live領域を使用すると、スクリーンリーダーにコンテンツの変更をアナウンスできます。'polite'は現在のアナウンスが終了するのを待ち、'assertive'はすぐに中断します。

アクセシブルなアイコンボタン

悪い例

説明のないボタン

これらのボタンにはテキスト指示がありません:

問題点:
  • スクリーンリーダーは「ボタン」とだけアナウンス
  • アイコンを見ずにアクションを知ることは不可能
  • 絵文字は誤解される可能性がある
  • ホバー時のツールチップがない

良い例

アクセシブルなボタン

アイコンをアクセシブルにするいくつかのアプローチ:

1. aria-labelを使用
2. 可視テキストを使用
3. 視覚的に隠されたテキストを使用
ベストプラクティス:
  • 常に代替テキストを提供(aria-label、隠しテキスト、または可視テキスト)
  • 装飾的なアイコンにはaria-hidden="true"を使用
  • title属性でツールチップを追加
  • スペースが許す場合は可視テキストを優先

説明: アイコンのみを含むボタンには、スクリーンリーダーが理解できるようにaria-labelまたは視覚的に隠されたテキストが必要です。

コンボボックス / 候補付き検索

悪い例

ARIAまたはキーボードナビゲーションなし

良い例

ARIAとキーボードナビゲーションを使用

0 件の結果があります

説明: 候補付き検索(コンボボックス)は、キーボードでナビゲート可能で、結果をアナウンスし、選択を許可する必要があります。

トースト通知(Live Regions)

悪い例

aria-liveなし

❌ 通知がスクリーンリーダーにアナウンスされない

<!-- 悪い例:スクリーンリーダーにアナウンスされない -->
<div v-if="showToast" class="toast">
  Votre demande a été enregistrée
</div>

良い例

適切なaria-liveを使用

✅ 通知が適切にアナウンスされる

<!-- 良い例:情報通知(polite) -->
<div
  v-if="showToast"
  role="status"
  aria-live="polite"
  aria-atomic="true"
  class="toast"
>
  <p>Votre demande a été enregistrée</p>
  <button @click="dismiss" aria-label="Fermer notification">✕</button>
</div>

<!-- 良い例:エラーアラート(assertive) -->
<div
  v-if="showError"
  role="alert"
  aria-live="assertive"
  aria-atomic="true"
  class="toast error"
>
  <p>Erreur : action impossible à exécuter</p>
  <button @click="dismiss" aria-label="Fermer alerte">✕</button>
</div>
違い:
  • role="status" + aria-live="polite":情報通知用、現在の読み上げを中断しない
  • role="alert" + aria-live="assertive":重大なエラー用、すぐに中断
  • aria-atomic="true":通知コンテンツ全体をアナウンス

説明: 動的通知は、フォーカスを奪うことなくスクリーンリーダーにアナウンスされる必要があります。情報にはrole='status'を、エラーにはrole='alert'を使用します。