【Javascript】モーダルウィンドウを実装する

モーダルウィンドウ



当記事では、モーダルウィンドウを実装する方法について記します。
dialog要素を使う事で簡単に作れます。





⓪dialog要素とは

dialog要素はHTML5から導入されました。モーダルウインドウの見た目を備えているのでCSSの記述をかなり抑えられます(Javascriptは依然必要ですが)。
また、モーダルを開いている時にコンテンツ以外にフォーカスが当たらないようにしてくれます。


dialog要素はすでに主要なブラウザでサポートされているようです。
参考:https://caniuse.com/?search=dialog





    ①モーダルウィンドウのパーツを用意する

    モーダルウィンドウで表示したいコンテンツをdialogタグで囲みます。
    モーダルウィンドウを開くボタンと閉じるボタンも用意しておきましょう。

    <button class="dialog-open">モーダルウィンドウを開く</button>
    <dialog>
      <button class="dialog-close cloase-btn">×</button>
        <img src="./img/sample.png">
    </dialog>







    ②モーダルウィンドウを開く

    dialog要素に対してshowModalメソッドを実行する事でモーダルウィンドウが開きます。
    トリガーとなるボタンがクリックされたら隣のdialog要素を取得してshowModalメソッドを実行します。

    document.addEventListener('click', (e, elem = e.target) => {
        elem.classList.contains('dialog-open') && elem.nextElementSibling.showModal()
    })





    ③閉じるボタンクリックでモーダルウィンドウを閉じる

    Javascriptでdialog要素に対してcloseメソッドを実行する事でモーダルウィンドウが閉じます。
    閉じるボタンがクリックされたら親のdialog要素を取得してcloseメソッドを実行します。

    document.addEventListener('click', (e, elem = e.target) => {
        elem.classList.contains('dialog-open') && elem.nextElementSibling.showModal()
        elem.classList.contains('dialog-close') && elem.closest('dialog').close()   // 追加
    })


    閉じるボタンのスタイル例です。
    ここでは、右上にXマークとして配置するようにします。

    dialog .cloase-btn {
        position: absolute;
        cursor: pointer;
        top: 6px;
        right: 6px;
        font-size: 36px;
    }


    閉じるボタンが出来たはずなので、試してみてください。






    ④背景クリックでモーダルウィンドウを閉じる

    背景をクリックした時にもモーダルウィンドウを閉じれるようにしましょう。
    閉じる機能は先ほど実装したので、dialog要素にクラスを追加するだけでOKです。

    <!-- <dialog> -->               <!-- 削除 -->
    <dialog class="dialog-close">   <!-- 追加 -->
        <button class="dialog-close cloase-btn">×</button>
        <img src="img/sample.png">
    </dialog>


    背景クリックで閉じるようになったと思います。






    ⑤スクロールの伝搬を防ぐ

    コンテンツが枠に収まらないほど長い時、dialog要素は自動でスクロールできるようにしてくれます。
    しかし、モーダル内のコンテンツをスクロールし終わった後にもう一度スクロールしてしまうと、モーダル外のコンテンツがスクロールされてしまうという問題が残ります。

    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa




    この問題を解決するにはoverscroll-behaviorプロパティが役に立ちます。

    dialog {
        overscroll-behavior-y: none;
    }

    スクロールが伝搬しないようになったと思うので、試してみてください。

    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa






    ⑥背景色を変更する

    背景色は::backdrop疑似要素で変更する事ができます。

    dialog::backdrop {
        background: #1119;
    }






    ⑦モーダルウィンドウを開く時のアニメーション

    モーダルウィンドウを開く時にフェードインを付けてみましょう。

    dialog {
        overscroll-behavior-y: none;
        animation: fadeIn 2s forwards;  /* 追記 */
    }
    
    /******** 追記 ********/
    @keyframes fadeIn{
        from { opacity: 0 }
        to   { opacity: 1 }
    }


    モーダルウィンドウがゆっくり表示されるようになったと思います。






    ソースコード全文

    最後にソースコードを全文載せておきます。

    <style>
        dialog {
            overscroll-behavior-y: none;
            animation: fadeIn 2s forwards;
        }
        dialog::backdrop {
            background: #1119;
        }
        dialog .cloase-btn {
            position: absolute;
            cursor: pointer;
            top: 0;
            right: 0;
            font-size: 36px;
        }
        @keyframes fadeIn{
            from { opacity: 0 }
            to   { opacity: 1 }
        }
    </style>
    
    <button class="dialog-open">モーダルウィンドウを開く</button>
    <dialog class="dialog-close">
        <button class="dialog-close cloase-btn">×</button>
        <img src="./img/sample.png">
    </dialog>
    
    <script>
        document.addEventListener('click', (e, elem = e.target) => {
            elem.classList.contains('dialog-open') && elem.nextElementSibling.showModal()
            elem.classList.contains('dialog-close') && elem.closest('dialog').close()
        })
    </script>








    以上、モーダルウィンドウを実装する方法でした!

    スポンサーリンク

    You can subscribe by SNS

    スポンサーリンク