JavaScriptでイベントリスナーを使ったモーダルウィンドウの制御方法

モーダルウィンドウは、ウェブページ上でユーザーに対して重要な情報を表示したり、特定の操作を促すために使用されるポップアップウィンドウです。通常、ページの背後を暗くして強調表示されるため、ユーザーの注目を集める効果があります。モーダルウィンドウは、ログインフォーム、警告メッセージ、確認ダイアログなど、様々な用途で活用されます。

本記事では、JavaScriptを用いてイベントリスナーを使い、モーダルウィンドウを効果的に制御する方法について詳しく解説します。モーダルウィンドウの基本概念から始まり、HTMLやCSSでの実装方法、さらにJavaScriptを用いた開閉の制御方法、アクセシビリティ対応、応用例までをカバーします。これにより、モーダルウィンドウを自在に操るスキルを身につけることができます。

目次
  1. モーダルウィンドウの基本概念
    1. モーダルウィンドウの定義
    2. モーダルウィンドウの使用例
  2. JavaScriptのイベントリスナーの概要
    1. イベントリスナーの仕組み
    2. 基本的な使い方
  3. モーダルウィンドウのHTML構造
    1. モーダルウィンドウの基本的なHTML構造
    2. 各要素の説明
  4. モーダルウィンドウのCSSスタイリング
    1. モーダルウィンドウの基本スタイル
    2. 各CSSプロパティの説明
  5. JavaScriptでモーダルの開閉を制御する
    1. モーダルウィンドウの開閉を制御するJavaScriptコード
    2. コードの詳細説明
    3. 実装のポイント
  6. モーダルウィンドウの外部クリックで閉じる方法
    1. モーダル外部クリックで閉じるJavaScriptコード
    2. コードの詳細説明
    3. 実装のポイント
  7. エスケープキーでモーダルを閉じる方法
    1. エスケープキーでモーダルを閉じるJavaScriptコード
    2. コードの詳細説明
    3. 実装のポイント
  8. モーダルウィンドウのアニメーション効果
    1. アニメーション効果を追加するCSSコード
    2. アニメーション効果を制御するJavaScriptコード
    3. コードの詳細説明
  9. モーダルウィンドウのアクセシビリティ対応
    1. ARIA属性を使用したアクセシビリティ対応
    2. フォーカス管理
    3. フォーカストラップの実装
  10. 応用例:複数のモーダルウィンドウを管理する方法
    1. 複数のモーダルウィンドウのHTML構造
    2. 複数のモーダルウィンドウを管理するJavaScriptコード
    3. コードの詳細説明
  11. まとめ

モーダルウィンドウの基本概念

モーダルウィンドウとは、ユーザーが他の操作を行う前に対話を必要とするポップアップウィンドウのことを指します。これは、通常、ユーザーに重要な情報を伝えたり、特定のアクションを促すために使用されます。

モーダルウィンドウの定義

モーダルウィンドウは、ウェブページの他の部分を操作できなくすることで、ユーザーの注目を特定の内容に集中させます。背景を暗くしてユーザーに対して「この内容に注意を払ってください」と強調します。

モーダルウィンドウの使用例

  • ログインフォーム:ユーザーがウェブサイトにアクセスする際にログイン情報を入力させるために使用されます。
  • 警告メッセージ:ユーザーが重要な決定をする前に確認を求めるメッセージを表示します。
  • フォーム入力:長いフォームを入力する際に、ユーザーがページをスクロールせずに済むように表示します。

モーダルウィンドウは、ユーザーエクスペリエンスを向上させるための強力なツールですが、過度に使用すると逆効果となるため、適切な場面で利用することが重要です。

JavaScriptのイベントリスナーの概要

JavaScriptのイベントリスナーは、ユーザーのアクション(クリック、キー押下、マウス移動など)に応じて特定の処理を実行するための機能です。イベントリスナーを適切に使用することで、インタラクティブなウェブアプリケーションを構築することができます。

イベントリスナーの仕組み

イベントリスナーは、指定されたイベントが発生した時に呼び出される関数を設定します。例えば、ボタンがクリックされた時にモーダルウィンドウを表示する処理を実行する場合、クリックイベントに対するイベントリスナーを設定します。

document.getElementById('myButton').addEventListener('click', function() {
    // モーダルウィンドウを表示する処理
    document.getElementById('myModal').style.display = 'block';
});

基本的な使い方

イベントリスナーの設定は、以下の手順で行います。

  1. ターゲット要素を選択:イベントを監視する要素(例えばボタンやリンク)をDOMから取得します。
  2. イベントの種類を指定:クリック、マウスオーバー、キープレスなど、監視したいイベントの種類を指定します。
  3. コールバック関数を定義:イベント発生時に実行する関数を定義します。

以下は、ボタンがクリックされた時にアラートを表示するシンプルな例です。

const button = document.getElementById('alertButton');
button.addEventListener('click', function() {
    alert('ボタンがクリックされました!');
});

イベントリスナーを使うことで、ユーザーのアクションに応じた動的な処理を簡単に追加できます。この基本的な仕組みを理解することで、モーダルウィンドウの開閉など、より複雑なインタラクションを実装する準備が整います。

モーダルウィンドウのHTML構造

モーダルウィンドウを作成するためには、基本的なHTML構造を理解し、適切にマークアップすることが重要です。ここでは、シンプルなモーダルウィンドウのHTMLテンプレートを示します。

モーダルウィンドウの基本的なHTML構造

モーダルウィンドウの基本的なHTML構造は以下の通りです。この構造には、モーダル本体、ヘッダー、コンテンツ、フッター、および閉じるボタンが含まれます。

<!-- トリガーボタン -->
<button id="openModalBtn">モーダルを開く</button>

<!-- モーダルウィンドウ -->
<div id="myModal" class="modal">
  <!-- モーダルのコンテンツ -->
  <div class="modal-content">
    <div class="modal-header">
      <span class="close-btn">&times;</span>
      <h2>モーダルウィンドウのタイトル</h2>
    </div>
    <div class="modal-body">
      <p>ここにモーダルの内容が表示されます。</p>
    </div>
    <div class="modal-footer">
      <h3>モーダルのフッター</h3>
    </div>
  </div>
</div>

各要素の説明

  • トリガーボタン:モーダルウィンドウを開くためのボタンです。このボタンに対してイベントリスナーを設定し、クリック時にモーダルを表示させます。
  • モーダルウィンドウ:モーダル本体を表す要素です。id属性とclass属性を持ち、スタイリングとスクリプトの対象となります。
  • モーダルのコンテンツ:モーダルの内容を含むコンテナです。ヘッダー、ボディ、フッターのセクションに分かれています。
  • モーダルヘッダー:モーダルのタイトルと閉じるボタンを含みます。
  • モーダルボディ:メインコンテンツが表示される部分です。
  • モーダルフッター:追加情報やボタンを配置するための領域です。

この基本構造を基に、CSSとJavaScriptを追加することで、完全なモーダルウィンドウを実装する準備が整います。次に、モーダルウィンドウのスタイリングについて説明します。

モーダルウィンドウのCSSスタイリング

モーダルウィンドウを視覚的に魅力的かつ機能的にするためには、適切なCSSスタイリングが重要です。ここでは、モーダルウィンドウの基本的なスタイルを設定する方法を説明します。

モーダルウィンドウの基本スタイル

以下に、モーダルウィンドウの基本的なスタイリングを示します。このスタイルは、モーダルウィンドウを中央に配置し、背景を半透明にすることで、ユーザーの注目を集めるデザインを実現します。

/* モーダルウィンドウの背景 */
.modal {
  display: none; /* 初期状態では非表示 */
  position: fixed; /* スクロールしても画面に固定 */
  z-index: 1; /* 他の要素の上に表示 */
  left: 0;
  top: 0;
  width: 100%; /* 全画面の幅 */
  height: 100%; /* 全画面の高さ */
  overflow: auto; /* 必要に応じてスクロール */
  background-color: rgba(0, 0, 0, 0.4); /* 半透明の黒い背景 */
}

/* モーダルコンテンツ */
.modal-content {
  background-color: #fff;
  margin: 15% auto; /* 上下に15%の余白、中央寄せ */
  padding: 20px;
  border: 1px solid #888;
  width: 80%; /* 幅80% */
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); /* 影を付けて浮き上がらせる */
}

/* モーダルヘッダー */
.modal-header {
  padding: 10px;
  border-bottom: 1px solid #ddd;
}

/* モーダルボディ */
.modal-body {
  padding: 10px;
}

/* モーダルフッター */
.modal-footer {
  padding: 10px;
  border-top: 1px solid #ddd;
}

/* 閉じるボタン */
.close-btn {
  color: #aaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close-btn:hover,
.close-btn:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}

各CSSプロパティの説明

  • .modal: モーダルウィンドウ全体の背景を設定しています。display: noneで初期状態を非表示にし、position: fixedで画面全体に固定し、background-color: rgba(0, 0, 0, 0.4)で半透明の黒い背景を作成しています。
  • .modal-content: モーダルの内容部分のスタイルです。中央寄せにし、白い背景と影を付けることで浮き上がって見えるようにしています。
  • .modal-header, .modal-body, .modal-footer: それぞれモーダルのヘッダー、ボディ、フッターのスタイルです。パディングを追加して内部の余白を確保し、ボーダーで区切っています。
  • .close-btn: モーダルを閉じるボタンのスタイルです。右上に配置し、ホバーやフォーカス時に色が変わるようにしています。

このCSSスタイルを用いることで、基本的なモーダルウィンドウのデザインを整えることができます。次に、JavaScriptを用いてモーダルウィンドウの開閉を制御する方法を説明します。

JavaScriptでモーダルの開閉を制御する

モーダルウィンドウを開閉するためには、JavaScriptを使ってイベントリスナーを設定し、ユーザーのアクションに応じてモーダルの表示・非表示を制御します。ここでは、基本的な開閉の実装方法を説明します。

モーダルウィンドウの開閉を制御するJavaScriptコード

以下に、モーダルウィンドウの開閉を実装するためのJavaScriptコードを示します。

// モーダルウィンドウを開くボタン
const openModalBtn = document.getElementById('openModalBtn');
// モーダルウィンドウ本体
const modal = document.getElementById('myModal');
// モーダルを閉じるボタン(×)
const closeModalBtn = document.getElementsByClassName('close-btn')[0];

// モーダルを開く
openModalBtn.addEventListener('click', function() {
  modal.style.display = 'block';
});

// モーダルを閉じる
closeModalBtn.addEventListener('click', function() {
  modal.style.display = 'none';
});

// モーダルの外側をクリックして閉じる
window.addEventListener('click', function(event) {
  if (event.target == modal) {
    modal.style.display = 'none';
  }
});

コードの詳細説明

  • モーダルを開くボタン: openModalBtn は、モーダルを開くためのボタンです。クリックイベントリスナーを設定し、クリック時にモーダルを表示します。
  • モーダルウィンドウ本体: modal は、モーダルウィンドウ全体を指します。スタイルを変更することで表示・非表示を制御します。
  • モーダルを閉じるボタン: closeModalBtn は、モーダルを閉じるためのボタン(×)です。クリックイベントリスナーを設定し、クリック時にモーダルを非表示にします。
  • モーダルの外側をクリックして閉じる: ウィンドウ全体にクリックイベントリスナーを設定し、モーダルの外側をクリックした場合にモーダルを閉じる処理を実装しています。

実装のポイント

  1. モーダルを開く: ボタンのクリックイベントをキャッチし、モーダルのスタイルを display: 'block' に変更します。
  2. モーダルを閉じる: 閉じるボタンのクリックイベントをキャッチし、モーダルのスタイルを display: 'none' に変更します。
  3. モーダルの外側をクリックして閉じる: イベントのターゲットがモーダル自体であることを確認し、モーダルを閉じます。

このようにして、JavaScriptを使ってモーダルウィンドウの開閉を制御する基本的な機能を実装することができます。次に、モーダルウィンドウの外部クリックで閉じる方法について詳しく説明します。

モーダルウィンドウの外部クリックで閉じる方法

ユーザーがモーダルウィンドウの外側をクリックしたときにモーダルを閉じる機能を追加することで、ユーザーエクスペリエンスを向上させることができます。この機能は、ユーザーが簡単にモーダルを閉じることができるようにするために役立ちます。

モーダル外部クリックで閉じるJavaScriptコード

以下に、モーダルウィンドウの外側をクリックして閉じるためのJavaScriptコードを示します。

// モーダルウィンドウを開くボタン
const openModalBtn = document.getElementById('openModalBtn');
// モーダルウィンドウ本体
const modal = document.getElementById('myModal');
// モーダルを閉じるボタン(×)
const closeModalBtn = document.getElementsByClassName('close-btn')[0];

// モーダルを開く
openModalBtn.addEventListener('click', function() {
  modal.style.display = 'block';
});

// モーダルを閉じる
closeModalBtn.addEventListener('click', function() {
  modal.style.display = 'none';
});

// モーダルの外側をクリックして閉じる
window.addEventListener('click', function(event) {
  if (event.target == modal) {
    modal.style.display = 'none';
  }
});

コードの詳細説明

  • モーダルを開くボタン: openModalBtnは、モーダルを開くためのボタンであり、クリックイベントを監視してモーダルを表示します。
  • モーダルウィンドウ本体: modalは、モーダルウィンドウ全体を表し、スタイルを変更することで表示・非表示を制御します。
  • モーダルを閉じるボタン: closeModalBtnは、モーダルを閉じるためのボタンであり、クリックイベントを監視してモーダルを非表示にします。
  • モーダルの外側をクリックして閉じる: window全体にクリックイベントリスナーを設定し、クリックイベントのターゲットがモーダルウィンドウ本体であるかどうかをチェックします。もしターゲットがモーダルウィンドウ本体であれば、モーダルを閉じる処理を実行します。

実装のポイント

  1. イベントターゲットの確認: クリックイベントが発生した際に、そのターゲットがモーダルウィンドウ本体であることを確認します。これにより、モーダルの外側をクリックした場合にのみモーダルを閉じることができます。
  2. スタイルの変更: モーダルウィンドウを閉じる際には、modal.style.display = 'none'として、モーダルを非表示にします。

この実装により、ユーザーがモーダルウィンドウの外側をクリックすることでモーダルを閉じることができるようになります。次に、キーボードのエスケープキーでモーダルを閉じる方法について説明します。

エスケープキーでモーダルを閉じる方法

モーダルウィンドウをユーザーがキーボードのエスケープキー(Escキー)で閉じる機能を追加することで、さらに使いやすくすることができます。これにより、ユーザーがマウスを使用せずにモーダルを簡単に閉じることが可能になります。

エスケープキーでモーダルを閉じるJavaScriptコード

以下に、エスケープキーでモーダルウィンドウを閉じるためのJavaScriptコードを示します。

// モーダルウィンドウを開くボタン
const openModalBtn = document.getElementById('openModalBtn');
// モーダルウィンドウ本体
const modal = document.getElementById('myModal');
// モーダルを閉じるボタン(×)
const closeModalBtn = document.getElementsByClassName('close-btn')[0];

// モーダルを開く
openModalBtn.addEventListener('click', function() {
  modal.style.display = 'block';
});

// モーダルを閉じる
closeModalBtn.addEventListener('click', function() {
  modal.style.display = 'none';
});

// モーダルの外側をクリックして閉じる
window.addEventListener('click', function(event) {
  if (event.target == modal) {
    modal.style.display = 'none';
  }
});

// エスケープキーでモーダルを閉じる
document.addEventListener('keydown', function(event) {
  if (event.key === 'Escape') {
    modal.style.display = 'none';
  }
});

コードの詳細説明

  • モーダルを開くボタン: openModalBtnは、モーダルを開くためのボタンであり、クリックイベントを監視してモーダルを表示します。
  • モーダルウィンドウ本体: modalは、モーダルウィンドウ全体を表し、スタイルを変更することで表示・非表示を制御します。
  • モーダルを閉じるボタン: closeModalBtnは、モーダルを閉じるためのボタンであり、クリックイベントを監視してモーダルを非表示にします。
  • モーダルの外側をクリックして閉じる: window全体にクリックイベントリスナーを設定し、クリックイベントのターゲットがモーダルウィンドウ本体であるかどうかをチェックします。もしターゲットがモーダルウィンドウ本体であれば、モーダルを閉じる処理を実行します。
  • エスケープキーでモーダルを閉じる: document全体にキーダウンイベントリスナーを設定し、押されたキーがエスケープキー(’Escape’)であるかどうかをチェックします。エスケープキーが押された場合、モーダルを非表示にします。

実装のポイント

  1. キーダウンイベントのリスナー設定: document.addEventListener('keydown', function(event) { ... });を使用して、キーボードのキーが押されたときのイベントを監視します。
  2. エスケープキーの判定: イベントオブジェクトのkeyプロパティを使用して、押されたキーがエスケープキー(’Escape’)であるかを判定します。該当する場合、モーダルを閉じる処理を実行します。

この実装により、ユーザーはエスケープキーを押すことでモーダルウィンドウを簡単に閉じることができます。次に、モーダルウィンドウの開閉時にアニメーション効果を追加する方法について説明します。

モーダルウィンドウのアニメーション効果

モーダルウィンドウの開閉時にアニメーション効果を追加することで、ユーザー体験を向上させ、より洗練されたインターフェースを提供することができます。ここでは、CSSトランジションを用いて簡単なアニメーション効果を実装する方法を説明します。

アニメーション効果を追加するCSSコード

まず、モーダルウィンドウの表示・非表示のトランジションを設定するためのCSSコードを追加します。

/* モーダルウィンドウの背景 */
.modal {
  display: none; /* 初期状態では非表示 */
  position: fixed; /* スクロールしても画面に固定 */
  z-index: 1; /* 他の要素の上に表示 */
  left: 0;
  top: 0;
  width: 100%; /* 全画面の幅 */
  height: 100%; /* 全画面の高さ */
  overflow: auto; /* 必要に応じてスクロール */
  background-color: rgba(0, 0, 0, 0.4); /* 半透明の黒い背景 */
  opacity: 0; /* 初期状態で透明 */
  transition: opacity 0.3s ease; /* フェードイン・フェードアウトのトランジション */
}

/* モーダルコンテンツ */
.modal-content {
  background-color: #fff;
  margin: 15% auto; /* 上下に15%の余白、中央寄せ */
  padding: 20px;
  border: 1px solid #888;
  width: 80%; /* 幅80% */
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); /* 影を付けて浮き上がらせる */
  transform: scale(0.7); /* 初期状態で縮小 */
  transition: transform 0.3s ease; /* 拡大縮小のトランジション */
}

.modal.show {
  display: block;
  opacity: 1; /* 表示状態で不透明 */
}

.modal-content.show {
  transform: scale(1); /* 表示状態で通常サイズ */
}

アニメーション効果を制御するJavaScriptコード

次に、モーダルウィンドウの表示・非表示を制御するJavaScriptコードに、アニメーション効果のクラスを追加します。

// モーダルウィンドウを開くボタン
const openModalBtn = document.getElementById('openModalBtn');
// モーダルウィンドウ本体
const modal = document.getElementById('myModal');
// モーダルを閉じるボタン(×)
const closeModalBtn = document.getElementsByClassName('close-btn')[0];

// モーダルを開く
openModalBtn.addEventListener('click', function() {
  modal.classList.add('show');
  const modalContent = modal.querySelector('.modal-content');
  modalContent.classList.add('show');
});

// モーダルを閉じる
closeModalBtn.addEventListener('click', function() {
  modal.classList.remove('show');
  const modalContent = modal.querySelector('.modal-content');
  modalContent.classList.remove('show');
  setTimeout(function() {
    modal.style.display = 'none';
  }, 300); // トランジション時間(0.3秒)後に非表示
});

// モーダルの外側をクリックして閉じる
window.addEventListener('click', function(event) {
  if (event.target == modal) {
    modal.classList.remove('show');
    const modalContent = modal.querySelector('.modal-content');
    modalContent.classList.remove('show');
    setTimeout(function() {
      modal.style.display = 'none';
    }, 300); // トランジション時間(0.3秒)後に非表示
  }
});

// エスケープキーでモーダルを閉じる
document.addEventListener('keydown', function(event) {
  if (event.key === 'Escape') {
    modal.classList.remove('show');
    const modalContent = modal.querySelector('.modal-content');
    modalContent.classList.remove('show');
    setTimeout(function() {
      modal.style.display = 'none';
    }, 300); // トランジション時間(0.3秒)後に非表示
  }
});

コードの詳細説明

  • CSSトランジション: .modal.modal-contentに対してtransitionプロパティを設定し、フェードイン・フェードアウトと拡大縮小のアニメーションを追加します。
  • JavaScriptでのクラス追加・削除: モーダルを開く際にshowクラスを追加し、閉じる際にshowクラスを削除します。これにより、CSSトランジションが適用されます。
  • タイムアウト処理: setTimeoutを使用して、トランジションが完了するまで(0.3秒)非表示にする処理を遅らせます。

この実装により、モーダルウィンドウの開閉時に滑らかなアニメーション効果を追加することができます。次に、モーダルウィンドウのアクセシビリティ対応について説明します。

モーダルウィンドウのアクセシビリティ対応

モーダルウィンドウを使用する際には、アクセシビリティに配慮することが重要です。これにより、すべてのユーザーがモーダルウィンドウを容易に利用できるようになります。ここでは、モーダルウィンドウのアクセシビリティ対応の基本を紹介します。

ARIA属性を使用したアクセシビリティ対応

ARIA(Accessible Rich Internet Applications)属性を使用することで、スクリーンリーダーなどの支援技術がモーダルウィンドウを正しく認識し、操作できるようにします。

<!-- トリガーボタン -->
<button id="openModalBtn" aria-haspopup="dialog" aria-controls="myModal">モーダルを開く</button>

<!-- モーダルウィンドウ -->
<div id="myModal" class="modal" role="dialog" aria-labelledby="modalTitle" aria-hidden="true">
  <!-- モーダルのコンテンツ -->
  <div class="modal-content">
    <div class="modal-header">
      <span class="close-btn" role="button" aria-label="閉じる">&times;</span>
      <h2 id="modalTitle">モーダルウィンドウのタイトル</h2>
    </div>
    <div class="modal-body">
      <p>ここにモーダルの内容が表示されます。</p>
    </div>
    <div class="modal-footer">
      <h3>モーダルのフッター</h3>
    </div>
  </div>
</div>

ARIA属性の説明

  • aria-haspopup: ボタンがモーダルウィンドウを開くことを示します。
  • aria-controls: ボタンが制御するモーダルウィンドウのIDを指定します。
  • role=”dialog”: モーダルウィンドウがダイアログであることを示します。
  • aria-labelledby: モーダルウィンドウのタイトルを指定します。
  • aria-hidden: 初期状態でモーダルが非表示であることを示します。
  • role=”button”: 閉じるボタンがボタンであることを示します。
  • aria-label: 閉じるボタンの説明を提供します。

フォーカス管理

モーダルウィンドウが表示された際に、適切な要素にフォーカスを設定し、閉じた際に元のフォーカス位置に戻すことで、ユーザーがモーダル内での操作をスムーズに行えるようにします。

// モーダルウィンドウを開くボタン
const openModalBtn = document.getElementById('openModalBtn');
// モーダルウィンドウ本体
const modal = document.getElementById('myModal');
// モーダルを閉じるボタン(×)
const closeModalBtn = document.getElementsByClassName('close-btn')[0];

// 元のフォーカス位置を保持
let focusedElementBeforeModal;

// モーダルを開く
openModalBtn.addEventListener('click', function() {
  focusedElementBeforeModal = document.activeElement; // 現在のフォーカス要素を保存
  modal.style.display = 'block';
  modal.setAttribute('aria-hidden', 'false'); // アクセシビリティ属性を更新
  const modalContent = modal.querySelector('.modal-content');
  modalContent.classList.add('show');
  modal.querySelector('[role="button"]').focus(); // モーダル内の最初のフォーカス要素にフォーカスを移動
});

// モーダルを閉じる
closeModalBtn.addEventListener('click', function() {
  modal.style.display = 'none';
  modal.setAttribute('aria-hidden', 'true'); // アクセシビリティ属性を更新
  const modalContent = modal.querySelector('.modal-content');
  modalContent.classList.remove('show');
  focusedElementBeforeModal.focus(); // モーダルを開く前の要素にフォーカスを戻す
});

// モーダルの外側をクリックして閉じる
window.addEventListener('click', function(event) {
  if (event.target == modal) {
    modal.style.display = 'none';
    modal.setAttribute('aria-hidden', 'true'); // アクセシビリティ属性を更新
    const modalContent = modal.querySelector('.modal-content');
    modalContent.classList.remove('show');
    focusedElementBeforeModal.focus(); // モーダルを開く前の要素にフォーカスを戻す
  }
});

// エスケープキーでモーダルを閉じる
document.addEventListener('keydown', function(event) {
  if (event.key === 'Escape') {
    modal.style.display = 'none';
    modal.setAttribute('aria-hidden', 'true'); // アクセシビリティ属性を更新
    const modalContent = modal.querySelector('.modal-content');
    modalContent.classList.remove('show');
    focusedElementBeforeModal.focus(); // モーダルを開く前の要素にフォーカスを戻す
  }
});

フォーカストラップの実装

モーダルウィンドウ内でTabキーを使用してもフォーカスがモーダル内に留まるようにするために、フォーカストラップを実装します。

modal.addEventListener('keydown', function(event) {
  const focusableElements = modal.querySelectorAll('a, button, textarea, input, select, [tabindex]:not([tabindex="-1"])');
  const firstFocusableElement = focusableElements[0];
  const lastFocusableElement = focusableElements[focusableElements.length - 1];

  if (event.key === 'Tab') {
    if (event.shiftKey) { // Shift + Tab
      if (document.activeElement === firstFocusableElement) {
        event.preventDefault();
        lastFocusableElement.focus();
      }
    } else { // Tab
      if (document.activeElement === lastFocusableElement) {
        event.preventDefault();
        firstFocusableElement.focus();
      }
    }
  }
});

この実装により、モーダルウィンドウがアクセシブルになり、キーボードのみを使用するユーザーや支援技術を使用するユーザーにも優しいインターフェースを提供できます。次に、複数のモーダルウィンドウを管理する方法について説明します。

応用例:複数のモーダルウィンドウを管理する方法

複数のモーダルウィンドウを同時に扱う場面では、それぞれのモーダルの開閉を適切に管理することが重要です。ここでは、複数のモーダルウィンドウを効率的に管理する方法を紹介します。

複数のモーダルウィンドウのHTML構造

まず、複数のモーダルウィンドウを定義するためのHTML構造を用意します。

<!-- トリガーボタン1 -->
<button class="open-modal-btn" data-modal="modal1">モーダル1を開く</button>
<!-- トリガーボタン2 -->
<button class="open-modal-btn" data-modal="modal2">モーダル2を開く</button>

<!-- モーダルウィンドウ1 -->
<div id="modal1" class="modal" role="dialog" aria-labelledby="modalTitle1" aria-hidden="true">
  <div class="modal-content">
    <div class="modal-header">
      <span class="close-btn" role="button" aria-label="閉じる">&times;</span>
      <h2 id="modalTitle1">モーダルウィンドウ1のタイトル</h2>
    </div>
    <div class="modal-body">
      <p>モーダル1の内容</p>
    </div>
    <div class="modal-footer">
      <h3>モーダル1のフッター</h3>
    </div>
  </div>
</div>

<!-- モーダルウィンドウ2 -->
<div id="modal2" class="modal" role="dialog" aria-labelledby="modalTitle2" aria-hidden="true">
  <div class="modal-content">
    <div class="modal-header">
      <span class="close-btn" role="button" aria-label="閉じる">&times;</span>
      <h2 id="modalTitle2">モーダルウィンドウ2のタイトル</h2>
    </div>
    <div class="modal-body">
      <p>モーダル2の内容</p>
    </div>
    <div class="modal-footer">
      <h3>モーダル2のフッター</h3>
    </div>
  </div>
</div>

複数のモーダルウィンドウを管理するJavaScriptコード

次に、複数のモーダルウィンドウを管理するためのJavaScriptコードを示します。

// すべてのトリガーボタンを取得
const openModalBtns = document.querySelectorAll('.open-modal-btn');

// モーダルウィンドウの開閉を管理する関数
function openModal(modalId) {
  const modal = document.getElementById(modalId);
  modal.classList.add('show');
  modal.setAttribute('aria-hidden', 'false');
  const modalContent = modal.querySelector('.modal-content');
  modalContent.classList.add('show');
  modal.querySelector('[role="button"]').focus();
}

function closeModal(modal) {
  modal.classList.remove('show');
  modal.setAttribute('aria-hidden', 'true');
  const modalContent = modal.querySelector('.modal-content');
  modalContent.classList.remove('show');
  setTimeout(() => {
    modal.style.display = 'none';
  }, 300);
}

// トリガーボタンにイベントリスナーを設定
openModalBtns.forEach(btn => {
  btn.addEventListener('click', () => {
    const modalId = btn.getAttribute('data-modal');
    openModal(modalId);
  });
});

// すべての閉じるボタンを取得
const closeModalBtns = document.querySelectorAll('.close-btn');

// 閉じるボタンにイベントリスナーを設定
closeModalBtns.forEach(btn => {
  btn.addEventListener('click', () => {
    const modal = btn.closest('.modal');
    closeModal(modal);
  });
});

// モーダルの外側をクリックして閉じる
window.addEventListener('click', event => {
  const modals = document.querySelectorAll('.modal.show');
  modals.forEach(modal => {
    if (event.target === modal) {
      closeModal(modal);
    }
  });
});

// エスケープキーでモーダルを閉じる
document.addEventListener('keydown', event => {
  if (event.key === 'Escape') {
    const modals = document.querySelectorAll('.modal.show');
    modals.forEach(modal => {
      closeModal(modal);
    });
  }
});

コードの詳細説明

  • トリガーボタンの設定: すべてのトリガーボタンにイベントリスナーを設定し、クリック時に対応するモーダルIDを取得してモーダルを開く関数を呼び出します。
  • モーダルの開閉関数: openModal関数は指定されたモーダルIDのモーダルを表示し、closeModal関数は指定されたモーダルを非表示にします。
  • 閉じるボタンの設定: すべての閉じるボタンにイベントリスナーを設定し、クリック時にモーダルを閉じる関数を呼び出します。
  • 外部クリックとエスケープキーの設定: ウィンドウ全体にクリックイベントリスナーとキーボードのエスケープキーイベントリスナーを設定し、モーダルの外側をクリックしたりエスケープキーが押されたときにすべての表示中のモーダルを閉じます。

このようにして、複数のモーダルウィンドウを効率的に管理し、ユーザーが直感的に操作できるインターフェースを提供することができます。次に、記事全体のまとめを行います。

まとめ

本記事では、JavaScriptを用いたモーダルウィンドウの制御方法について詳しく解説しました。基本的なモーダルウィンドウのHTML構造やCSSスタイリングから始まり、JavaScriptを使用してモーダルを開閉する方法を説明しました。また、外部クリックやエスケープキーでモーダルを閉じる実装方法、開閉時のアニメーション効果の追加、アクセシビリティ対応についても取り上げました。さらに、複数のモーダルウィンドウを管理するための実装方法も紹介しました。

モーダルウィンドウを適切に実装することで、ユーザーエクスペリエンスを向上させ、よりインタラクティブで使いやすいウェブアプリケーションを作成することができます。これらの技術を活用し、効果的なモーダルウィンドウを実装するスキルを身につけてください。

コメント

コメントする

目次
  1. モーダルウィンドウの基本概念
    1. モーダルウィンドウの定義
    2. モーダルウィンドウの使用例
  2. JavaScriptのイベントリスナーの概要
    1. イベントリスナーの仕組み
    2. 基本的な使い方
  3. モーダルウィンドウのHTML構造
    1. モーダルウィンドウの基本的なHTML構造
    2. 各要素の説明
  4. モーダルウィンドウのCSSスタイリング
    1. モーダルウィンドウの基本スタイル
    2. 各CSSプロパティの説明
  5. JavaScriptでモーダルの開閉を制御する
    1. モーダルウィンドウの開閉を制御するJavaScriptコード
    2. コードの詳細説明
    3. 実装のポイント
  6. モーダルウィンドウの外部クリックで閉じる方法
    1. モーダル外部クリックで閉じるJavaScriptコード
    2. コードの詳細説明
    3. 実装のポイント
  7. エスケープキーでモーダルを閉じる方法
    1. エスケープキーでモーダルを閉じるJavaScriptコード
    2. コードの詳細説明
    3. 実装のポイント
  8. モーダルウィンドウのアニメーション効果
    1. アニメーション効果を追加するCSSコード
    2. アニメーション効果を制御するJavaScriptコード
    3. コードの詳細説明
  9. モーダルウィンドウのアクセシビリティ対応
    1. ARIA属性を使用したアクセシビリティ対応
    2. フォーカス管理
    3. フォーカストラップの実装
  10. 応用例:複数のモーダルウィンドウを管理する方法
    1. 複数のモーダルウィンドウのHTML構造
    2. 複数のモーダルウィンドウを管理するJavaScriptコード
    3. コードの詳細説明
  11. まとめ