[ プログラミング ] jQueryでモーダルウィンドウを作る方法

[2014/12/20]
ソースコードにミスがあったので大幅に修正しました。

こちらの記事を見て、簡単にモーダルウィンドウが作れるようなので、試しに作ってみました。

あと、これだと複数のモーダルウィンドウが作れないので、以下の記事を参考に、複数バージョンにしてみました。

両サイトの方、ありがとうございます!

ちなみに、モーダルウィンドウとは、

モーダルウィンドウとは、操作が完了するまで親ウィンドウへの操作を受け付けなくさせるタイプのウィンドウのことである。 モーダルウィンドウが表示されると、その中で指定された操作を完了するかキャンセルするかして、そのウィンドウを閉じない限り、親ウィンドウ側に対する操作ができないようになる。このため、モーダルウィンドウはユーザーに特定の操作をさせたり、確認を促したりといった目的で用いられることが多い。

モーダルウィンドウとは (modal window): – IT用語辞典バイナリより引用

といったものです。

デモは以下からどうぞ。

DOMO

HTML5でコーディングしています。コードが少ないので、jQueryもCSSもHTMLのheadタグ内に書いています。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>[DEMO]jQueryでモーダルウィンドウを作る方法</title>
<script src="js/jquery.js"></script>
<script>
$(function(){
    // 「.modal-open」をクリック
    $('.modal-open').click(function(){
        // オーバーレイ用の要素を追加
        $('body').append('<div class="modal-overlay"></div>');
        // オーバーレイをフェードイン
        $('.modal-overlay').fadeIn('slow');

        // モーダルコンテンツのIDを取得
        var modal = '#' + $(this).attr('data-target');
        // モーダルコンテンツの表示位置を設定
        modalResize();
         // モーダルコンテンツフェードイン
        $(modal).fadeIn('slow');

        // 「.modal-overlay」あるいは「.modal-close」をクリック
        $('.modal-overlay, .modal-close').off().click(function(){
            // モーダルコンテンツとオーバーレイをフェードアウト
            $(modal).fadeOut('slow');
            $('.modal-overlay').fadeOut('slow',function(){
                // オーバーレイを削除
                $('.modal-overlay').remove();
            });
        });

        // リサイズしたら表示位置を再取得
        $(window).on('resize', function(){
            modalResize();
        });

        // モーダルコンテンツの表示位置を設定する関数
        function modalResize(){
            // ウィンドウの横幅、高さを取得
            var w = $(window).width();
            var h = $(window).height();

            // モーダルコンテンツの表示位置を取得
            var x = (w - $(modal).outerWidth(true)) / 2;
            var y = (h - $(modal).outerHeight(true)) / 2;

            // モーダルコンテンツの表示位置を設定
            $(modal).css({'left': x + 'px','top': y + 'px'});
        }

    });
});
</script>

<style>
.modal-content {
    position:fixed;
    display:none;
    z-index:2;
    width:50%;
    margin:0;
    padding:10px 20px;
    border:2px solid #aaa;
    background:#fff;
}

.modal-content p {
    margin:0;
    padding:0;
}

.modal-overlay {
    z-index:1;
    display:none;
    position:fixed;
    top:0;
    left:0;
    width:100%;
    height:120%;
    background-color:rgba(0,0,0,0.75);
}

.modal-open {
    color:#00f;
    text-decoration:underline;
}

.modal-open:hover {
    cursor:pointer;
    color:#f00;
}

.modal-close {
    color:#00f;
    text-decoration:underline;
}

.modal-close:hover {
    cursor:pointer;
    color:#f00;
}
</style>
</head>
<body>
<a data-target="con1" class="modal-open">リンク1</a>
<a data-target="con2" class="modal-open">リンク2</a>
<a data-target="con3" class="modal-open">リンク3</a>
<a data-target="con4" class="modal-open">リンク4</a>
<a data-target="con5" class="modal-open">リンク5</a>

<div id="con1" class="modal-content">
    <p>リンク1の内容です。</p>
    <p><a class="modal-close">閉じる</a></p>
</div>
<div id="con2" class="modal-content">
    <p>リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。リンク2の内容です。</p>
    <p><a class="modal-close">閉じる</a></p>
</div>
<div id="con3" class="modal-content">
    <p>リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。リンク3の内容です。</p>
    <p><a class="modal-close">閉じる</a></p>
</div>
<div id="con4" class="modal-content">
    <p>リンク4の内容です。リンク4の内容です。</p>
    <p><a class="modal-close">閉じる</a></p>
</div>
<div id="con5" class="modal-content">
    <p>リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。リンク5の内容です。</p>
    <p><a class="modal-close">閉じる</a></p>
</div>
<p>
スクロールしてみてください。モーダルウィンドウは固定されているのがわかるかと思います。<br>
↓<br>
・・・
終わり。
</p>
<p><a href="http://coolwebwindow.com/jquery-lab/archives/304">&lt;&lt; 記事に戻る</a></p>
</body>
</html>

簡単に説明すると、リンクしたいテキストをアンカーで囲み(別にaタグでなくてもよいのですが、そのほうが意味的には通っているので)、「data-target」という新しい属性を作っています。これは元々ある属性ではなくて自分で勝手に作った属性になります。この属性に任意の文字列を与えます。「con1」とか「con2」とかです。

モーダルウィンドウで表示したいコンテンツをdiv要素で囲み、div要素に先ほど指定したdata-targetの値(文字列)をclass名にして指定します。

少し補足すると、この「data-target」というのは、「カスタムデータ属性(独自データ属性)」といい、HTML5から実装された定義です。名前の付け方も決まっており、「data-」から始める文字列で、その後の文字列の付け方も決まっています。以下のブログの記事では詳しく説明されているのでご参考ください。

jQueryの部分はソースコードを見てもらえばわかるかと思いますが、ちょっと引っかかったところは、オーバーレイのコンテンツを非表示にする箇所(27行目~)です。

フェードアウトした後に、「.remove()」を使って、オーバーレイのdiv要素(<div class=”modal-overlay”></div>)を削除しないと、モーダルウィンドウを表示する度に、オーバーレイのレイヤーが重なってしまいます。あと、フェードアウトした後に削除しないといけないので、コールバック関数を使います。

あと、Syncer様のサイトでもそうでしたが、、その前にクリックした分のイベントハンドラが残っているらしく、24行目で「$(‘.modal-overlay, .modal-close’).off().click(function(){~」というように「.off()」を入れないと動作がおかしくなりました。これはバグなのでしょうか…。よくわかりませんでした。

このモーダルウィンドウは反対に、スクロールバーの出るモーダルウィンドウを作ってみました。是非、ご参考ください。