モーダルウィンドウ(ポップアップ)の実装

このページの目的

ボタンなどをクリックした際に、画面の上にフワッと新しいウィンドウ(モーダルウィンドウ)を重ねて表示する機能の実装方法を学びます。
ユーザーの操作を妨げずに、補足情報や拡大画像、フォームなどを提示したい場合に非常に有効なテクニックです。

smart_display動作サンプル

以下のボタンをクリックすると、モーダルウィンドウが開きます。背景の黒い部分や、閉じるボタン(×)をクリックすると、ウィンドウが閉じます。

このサンプルを実装するためのHTML, CSS, JavaScriptのコードは以下の通りです。


code実装コード解説

1. HTMLの構造

モーダルを開くための「トリガー(ボタン)」と、モーダルウィンドウ本体(.modal-container)の2つの部分を用意します。

<!-- モーダルを開くボタン -->
<button type="button" class="button" aria-haspopup="dialog" aria-controls="my-modal">モーダルを開く</button>

<!-- モーダルウィンドウ本体 -->
<div id="my-modal" class="modal-container" role="dialog" aria-modal="true" aria-hidden="true">
  <!-- 半透明の背景オーバーレイ -->
  <div class="modal-overlay"></div>

  <!-- モーダルのコンテンツ部分 -->
  <div class="modal-content">
    <button class="modal-close-button" aria-label="閉じる">×</button>
    <h4 class="modal-title">タイトル</h4>
    <p>ここにコンテンツが入ります。</p>
  </div>
</div>

2. CSSのスタイル

普段はモーダルを非表示にしておき、.is-activeクラスが付いたら表示されるようにします。表示・非表示には`visibility`と`opacity`を使い、滑らかなアニメーションを実現します。

.modal-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  
  /* 普段は非表示 */
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s 0.3s, opacity 0.3s;
}
.modal-container.is-active {
  visibility: visible;
  opacity: 1;
  transition: visibility 0s 0s, opacity 0.3s;
}

.modal-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.6); /* 半透明の黒 */
}

.modal-content {
  position: relative; /* オーバーレイより手前に */
  width: 90%;
  max-width: 500px;
  background: #fff;
  padding: 2em;
  border-radius: 8px;
}
.modal-close-button {
  position: absolute;
  top: 10px;
  right: 10px;
  /* ...その他ボタンのスタイル... */
}

3. JavaScriptの処理

「開くボタン」と「閉じるボタン」がクリックされた時の処理を記述します。

function initModals() {
    const openTriggers = document.querySelectorAll('[aria-haspopup="dialog"]');
    
    openTriggers.forEach(trigger => {
        const modalId = trigger.getAttribute('aria-controls');
        const modal = document.getElementById(modalId);
        
        if (modal) {
            const closeTrigger = modal.querySelector('.modal-close-button');
            const overlay = modal.querySelector('.modal-overlay');

            // 開く処理
            trigger.addEventListener('click', () => {
                modal.classList.add('is-active');
                modal.setAttribute('aria-hidden', 'false');
            });
            
            // 閉じる処理
            const closeModal = () => {
                modal.classList.remove('is-active');
                modal.setAttribute('aria-hidden', 'true');
            };

            closeTrigger.addEventListener('click', closeModal);
            overlay.addEventListener('click', closeModal);
        }
    });
}

document.addEventListener('DOMContentLoaded', initModals);