【Javascript】1ページ内の複数モーダルウィンドウの実装方法 -作って学ぶWeb制作-

JavaScript実践練習コース

はじめに

作って学ぶWeb制作の中級編をご覧いただきありがとうございます!!
今回は1ページ内の複数モーダルウィンドウを実装していきます。
モーダルウィンドウは、ユーザーに重要な情報を伝えたり、エラーメッセージを通知する場合などによく使われるUIです。サイトを訪れた際にクーポンや新商品などがモーダルで表示されるのを見かけたことがある方もいると思います。

今回はページ内に複数のモーダルを設置し、それぞれの中身に違う内容を表示できるようにしていきます。

では今回作るもののデモと仕様を確認しましょう!

デモ

ページを下へスクロールすると右下にボタンが表示されます。クリックするとページの最上部へと移動します。

仕様

以下の仕様をもとに実装を進めていきます。

ボタンをクリックでそれぞれのモーダルを表示する

×アイコンまたは背景をクリックでモーダルを閉じる

“ふわっ”と表示されるフェードインアニメーションをつける

今回もcss、jsファイルは外部ファイルとしてhtmlで読み込みます。

 【実践】ページ内に複数のモーダルウィンドウを実装する

HTMLを準備する

モーダルの表示を制御するボタン、モーダル内部のコンテンツをHTMLに記載していきます。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1ページ内の複数モーダルウィンドウ サンプル</title>
    <link rel="stylesheet" href="style.css">
    <link href="https://use.fontawesome.com/releases/v6.7.2/css/all.css" rel="stylesheet">
</head>

<body>
    <header>
        <h1>作って学ぶWeb制作 中級</h1>
        <h2>1ページ内に複数モーダルウィンドウを作ってみよう</h2>
    </header>
    <!-- start main contents -->
    <main>
        <button class="open-modal open-btn" data-modal="1">モーダル1</button>
        <button class="open-modal open-btn" data-modal="2">モーダル2</button>

        <!-- モーダル本体 -->
        <div class="modal" id="modal-1">
            <div class="modal-content">
                <button class="close-btn" data-modal="1">
                    <i class="fa-solid fa-xmark" style="color: #5b370d;"></i>
                </button>
                <h2>これはモーダル1です</h2>
                <p>モーダルの中身にそれぞれ違う内容が表示できます</p>
            </div>
        </div>

        <div class="modal" id="modal-2">
            <div class="modal-content">
                <button class="close-btn" data-modal="2">
                    <i class="fa-solid fa-xmark" style="color: #5b370d;"></i>
                </button>
                <h2>これはモーダル2です</h2>
                <p>複数のモーダルが実装できます!</p>
            </div>
        </div>
        <!-- モーダル本体 -->
    </main>
    <!-- end main contents-->
    <script type="text/javascript" src="script.js"></script>
</body>
</html>

ソースコード ポイント解説

       <button class="open-modal open-btn" data-modal="1">モーダル1</button>
    <button class="open-modal open-btn" data-modal="2">モーダル2</button>

モーダルを開くボタンにdata-modal属性をつけています。これがボタンとモーダルを紐付ける役割をしています。

CSSでスタイルを追加する

今回はモーダル表示時のCSSアニメーションがポイントになります!

    * {
        box-sizing: border-box;
    }

    body {
        font-family: "Arial", sans-serif;
    }
    h1{
        font-size: 24px;
    }
    h2{
        font-size: 18px;
    }

    /* ボタン */
    .open-btn {
        background-color: #f7d96b;
        color: #5b370d;
        padding: 0.8rem 1.5rem;
        font-size: 1.2rem;
        font-weight: bold;
        border: none;
        border-radius: 10px;
        cursor: pointer;
        transition: background-color 0.3s ease;
        margin: 16px;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    }

    .open-btn:hover {
        background-color: #dfbb36;
    }

    .close-btn {
        position: absolute;
        top: 10px;
        right: 15px;
        font-size: 1.6rem;
        background: transparent;
        border: none;
        cursor: pointer;
        transition: transform 0.3s ease;
    }

    /* モーダル背景 */
    .modal {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
        background: rgba(79, 79, 79, 0.5);
        z-index: 100;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease;
    }

    /* モーダル表示状態 */
    .modal.active {
        display: flex;
        opacity: 1;
        pointer-events: auto;
    }

    /* モーダルの中身*/
    .modal-content {
        background: #fff;
        padding: 1rem;
        border-radius: 10px;
        width: 80vw;
        max-width: 500px;
        text-align: center;
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
        position: relative;
        opacity: 0;
        transform: scale(0.8);
        transition: all 0.3s ease;
    }

    /* アニメーション*/
    .modal.active .modal-content {
        animation: fadeInScale 0.4s ease forwards;
    }

    @keyframes fadeInScale {
        0% {
            opacity: 0;
            transform: scale(0.8);
        }
        100% {
            opacity: 1;
            transform: scale(1);
        }
    }

ソースコード ポイント解説

ふわっと浮き出て表示されるようなアニメーションにするために透過度とスケールに変化をつけています。
    @keyframes fadeInScale {
        0% {
            opacity: 0;
            transform: scale(0.8);
        }
        100% {
            opacity: 1;
            transform: scale(1);
        }
    }

scaleを0.8→1にしてモーダルを小さめから通常の大きさへ拡大する動きを、opacityを0→1で透明から100%表示にすることで”ふわっ”と感を演出しています。

Javascriptで複数モーダルの表示制御をする

最後にモーダルの表示制御を実装していきましょう。関数で処理を分けることで、モーダルの数が増えた時にも対応できるようにします。

    document.addEventListener('DOMContentLoaded', () => {
        modalTriggers();
    });

    //モーダルを開く・閉じる・背景クリックのイベントをまとめて設定
    function modalTriggers() {
        const openButtons = document.querySelectorAll('.open-modal');
        const closeButtons = document.querySelectorAll('.close-btn');
        const modals = document.querySelectorAll('.modal');


        openButtons.forEach(button => {
            button.addEventListener('click', () => {
                const modalId = button.dataset.modal;
                openModal(modalId);
            });
        });


        closeButtons.forEach(button => {
            button.addEventListener('click', () => {
                const modalId = button.dataset.modal;
                closeModal(modalId);
            });
        });


        //モーダルの背景クリックで閉じる
        modals.forEach(modal => {
            modal.addEventListener('click', e => {
                if (e.target.classList.contains('modal')) {
                    modal.classList.remove('active');
                }
            });
        });
    }


    //指定したIDのモーダルを開く関数
    function openModal(modalId) {
        const modal = document.getElementById(`modal-${modalId}`);
        if (modal) {
            modal.classList.add('active');
        }
    }


    //指定したIDのモーダルを閉じる関数
    function closeModal(modalId) {
        const modal = document.getElementById(`modal-${modalId}`);
        if (modal) {
            modal.classList.remove('active');
        }
    }

ソースコード ポイント解説

開く処理、閉じる処理をそれぞれ説明していきます。

    openButtons.forEach(button => {
        button.addEventListener('click', () => {
            const modalId = button.dataset.modal;
            openModal(modalId);
        });
    });
モーダルを開く処理ではまずボタンがクリックされたときにopenModal() 関数を呼び出します。どのモーダルを表示するか判断するためにHTML記載時に各ボタンにつけたdata-modal属性の値を取得し、そのmodalIdを元にどのモーダルを開くかを判断しています。
では次に呼び出すopenModal()関数で何をしているかみていきましょう。
    function openModal(modalId) {
        const modal = document.getElementById(`modal-${modalId}`);
        if (modal) {
            modal.classList.add('active');
        }
    }
modalId対応するモーダル要素を ID(例: modal-1)で取得します。
.activeクラスを追加してモーダルの要素を表示します。
続いて閉じる処理を解説していきます!
    closeButtons.forEach(button => {
        button.addEventListener('click', () => {
            const modalId = button.dataset.modal;
            closeModal(modalId);
        });
    });
閉じるボタンがクリックされたときに今度は閉じる処理のcloseModal() 関数を呼び出します。閉じるボタンにもdata-modal属性があるので開く処理と同様にして対応するモーダルを閉じています。呼び出すcloseModal()関数ではopenModal()関数の逆で.activeクラスを削除してモーダルを非表示にします。

ここまでで解説してきた処理はmodalTriggers()としてまとめられています。

    document.addEventListener('DOMContentLoaded', () => {
        modalTriggers();
    });

ページが完全に読み込まれた後に モーダルに対するイベントをすべてまとめているmodalTriggers()呼び出します。関数化することでモーダルの数を増やしたい場合にもHTMLの要素とCSSがあれば、同じ仕組みを再利用可能になります。

関数化するとコードも見やすくもなって、機能を追加したいときにもメンテしやすいですね

まとめ

今回の作って学ぶWeb制作中級編では1ページ内の複数モーダルウィンドウを実装してみました。複数モーダルを使うとページ遷移なしで詳細情報が表示できるため、ユーザーの離脱も防ぐ役割がありますね。ふわっとしたアニメーションも付けましたが、ちょっとした動きを加えることで、視覚的な効果もアップします!ユーザーのことを考えて細かい部分も工夫していきたいですね!
実装が参考になればうれしいです。お読みいただきありがとうございました。

タイトルとURLをコピーしました