ally.jsを使ったアクセシブルなダイアログの完全ガイド

ally.jsを使ったアクセシブルなダイアログの完全ガイド

現代のWeb開発において、ダイアログは一般的なUIコンポーネントですが、真正のアクセシビリティを備えたダイアログを実装するのは容易ではありません。本記事では、ally.jsプロジェクトを基に、WAI-ARIA 1.0仕様を完全に遵守した、美しく機能的なアクセシブルなダイアログの構築方法を詳しく解説します。

アクセシブルなダイアログとは?

アクセシブルなダイアログは、視覚的に魅力的であるだけでなく、以下の技術的な要件も満たす必要があります:

  1. キーボード操作対応:Tab、Shift+Tab、Enter、Escapeキーなどの操作をサポート
  2. スクリーンリーダー対応:ダイアログの役割、タイトル、説明を正しくラベル付け
  3. フォーカス管理:ダイアログ内でのフォーカスの流れを適切に制御
  4. 視覚的な分離:背景をぼかすオーバーレイでダイアログ内容を強調

HTML構造の設計

基本構造

<div id="modal" role="dialog" aria-labelledby="modal-title" 
     aria-describedby="modal-description" tabindex="-1" hidden>
  <form class="modal-content">
    <header>
      <h1 id="modal-title">氏名入力</h1>
      <p id="modal-description">ご自身のフルネームを入力してください</p>
    </header>
    <section>
      <label for="modal-input">氏名</label>
      <input id="modal-input">
    </section>
    <footer>
      <button type="button" id="close-modal">閉じる</button>
      <button type="submit" id="save-modal">保存</button>
    </footer>
  </form>
</div>

主要な属性の解説

  1. role="dialog":この要素がダイアログコンポーネントであることを明示的に示します。
  2. aria-labelledby:ダイアログのタイトルと関連付けます。
  3. aria-describedby:ダイアログの説明と関連付けます。
  4. tabindex="-1":要素をフォーカス可能にしますが、通常のTab順序には含めません。
  5. hidden:ダイアログを初期状態で非表示にします。

CSSによる視覚的実装

基本スタイル

#modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 999;
}

#modal::before {
  content: "";
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.3);
  z-index: 999;
  transition: opacity 0.2s ease-in-out;
}

.modal-content {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 300px;
  height: 200px;
  transform: translate3d(-50%, -50%, 0);
  padding: 20px;
  background: white;
  z-index: 1000;
  transition: transform 0.2s ease-in-out;
}

アニメーション効果の実装

#modal[hidden],
#modal[hidden]::before,
#modal[hidden] .modal-content {
  display: block;
  visibility: hidden;
  transform: translate3d(0px, -1px, 0px) scale(0);
  transition:
    visibility 0s linear 0.2s,
    transform 0s linear 0.2s;
}

#modal[hidden]::before {
  opacity: 0;
  transition:
    opacity 0.2s ease-in-out,
    visibility 0s linear 0.2s,
    transform 0s linear 0.2s;
}

#modal[hidden] .modal-content {
  transform: translate3d(0px, -1px, 0px) scale(0);
  transition:
    transform 0.2s ease-in-out,
    visibility 0s linear 0.2s;
}

JavaScriptによるインタラクションの実装

基本機能

const openModalBtn = document.getElementById('open-modal');
const modal = document.getElementById('modal');
const closeModalBtn = document.getElementById('close-modal');

function openModal() {
  modal.hidden = false;
}

function closeModal() {
  modal.hidden = true;
}

openModalBtn.addEventListener('click', openModal);
closeModalBtn.addEventListener('click', closeModal);

ally.jsによるアクセシビリティの強化

1. フォーカス制御
let disableHandle, focusHandle;

function openModal() {
  // ダイアログ外のすべてのフォーカス可能な要素を無効化
  disableHandle = ally.maintain.disabled({
    filter: modal,
  });
  
  // Tabキーがダイアログ内で循環するように制御
  focusHandle = ally.maintain.tabFocus({
    context: modal,
  });
  
  modal.hidden = false;
  
  // フォーカスをダイアログ内の最初のフォーカス可能な要素に移動
  ally.when.visible(modal, function() {
    const focusable = ally.query.firstTabbable({
      context: modal,
      defaultToContext: true,
    });
    focusable.focus();
  });
}

function closeModal() {
  disableHandle.disengage();
  focusHandle.disengage();
  modal.hidden = true;
}
2. キーボードイベント処理
// Escapeキーでダイアログを閉じる処理
const escapeKeyHandler = ally.when.key({
  escape: closeModal,
});

// フォーム送信処理
modal.querySelector('form').addEventListener('submit', function(event) {
  event.preventDefault();
  // フォームのバリデーションロジック...
  closeModal();
});

ベストプラクティスのまとめ

  1. セマンティックHTML:ARIA属性と役割を正しく使用する。
  2. フォーカス管理
    • ダイアログを開いた際に、最初のフォーカス可能な要素にフォーカスを移動する。
    • ダイアログを閉じた際に、元のトリガー要素にフォーカスを戻す。
    • Tabキーによるフォーカスをダイアログ内で循環させる。
  3. キーボードサポート
    • Tab/Shift+Tabによるダイアログ内のフォーカス移動。
    • Escapeキーによるダイアログの閉じる。
    • Enterキーによるフォームの送信。
  4. 視覚的なフィードバック
    • オーバーレイでダイアログを強調表示する。
    • スムーズな開閉アニメーションを追加する。
  5. スクリーンリーダー対応
    • 明確なタイトルと説明を提供する。
    • 背景コンテンツを非表示にする。

よくある問題と解決策

1. モバイルデバイスの互換性問題

モバイルデバイスでは、以下の点を推奨します:

  • <form>要素を使用して、仮想キーボードが適切な操作ボタンを表示するようにする。
  • ダイアログの幅を100%に設定して、小さい画面に対応する。
  • 固定の高さを避け、min-heightとスクロール機能を利用する。

2. 複雑なコンテンツの処理

内容が多いダイアログの場合:

  • 内部のスクロール可能な領域に適切なARIAラベルを付ける。
  • 「トップ/ボトムへスクロール」のショートカットを提供する。
  • ページネーションやタブインターフェースを検討する。

3. パフォーマンスの最適化

頻繁に開閉されるダイアログでは:

  • ダイアログを事前にレンダリングし、非表示のままにしておく。
  • CSSトランジションを使用し、レイアウトに影響を与えるプロパティは避ける。
  • アニメーション中のDOM操作を避ける。

これらの原則とally.jsが提供するツールを活用することで、開発者はすべてのユーザーにとって一貫した体験を提供する、美しく完全なアクセシビリティを備えたダイアログコンポーネントを構築できます。

タグ: ally.js ARIA ダイアログ アクセシビリティ javascript

6月6日 16:08 投稿