モーダルの処理を自作する

汎用的に流用できるような、簡易なモーダルを作成してみます。

サンプルコード

まずはモーダルを開くリンク部分です。
data属性で開くモーダルを設定するようにします。

1
2
<a href="" data-modal-link="modal-a">モーダルAを開く</a>
<a href="" data-modal-link="modal-b">モーダルBを開く</a>

data-modal-linkにモーダル名を指定してください。

次にモーダル部分です。
モーダルの要素にdata-modal-contentを設定して、先ほどリンクに設定したモーダル名を入れます。

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="modal-bg js-modalclose"></div>
<div class="modal" data-modal-content="modal-a">
  <p>モーダルAのコンテンツです。</p>
  <button class="js-modalclose">閉じる</button>
</div>
<!-- END modal-a -->
<div class="modal" data-modal-content="modal-b">
  <p>モーダルBのコンテンツです。</p>
  〜 略 〜
  <p>モーダルBのコンテンツです。</p>
  <button class="js-modalclose">閉じる</button>
</div>
<!-- END modal-b -->

.modal-bgがモーダルの背景、.modalがモーダル部分で、背景などに設定している.js-modalcloseはクリックしたらモーダルを閉じるようにJavaScriptで設定します。

次にCSSです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.modal-bg {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9500;
  background: rgba(0, 0, 0, 0.75);
}
.modal.is-show {
  display: block;
}
.modal {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  width: 600px;
  z-index: 9800;
  background: #ffffff;
  transform: translate(-50%, -50%);
}
.modal-bg.is-show {
  display: block;
}

.modal-bg、.modal共にデフォルトでは非表示にして、.is-showが付与されると表示されるように設定しています。

最後にJavaScriptです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$(function() {
    // モーダルを開く
    $(document).on('click', '[data-modal-link]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalLink');
        modal_open(target);
    });
 
    // モーダルを閉じる
    $('.js-modalclose').on('click', function(e) {
        e.preventDefault();
        modal_close();
    });
});
 
// モーダルを開く
function modal_open(target) {
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    $('.modal-bg').addClass('is-show');
}
 
// モーダルを閉じる
function modal_close() {
    $('[data-modal-content]').removeClass('is-show');
    $('.modal-bg').removeClass('is-show');
}

クリックしたdata属性の値を使って、対になるモーダルを表示したり閉じたりしています。
モーダルのデモページ

これで基本的な動作は問題ないのですが、モーダルの配置をposition: fixed;で中央配置にしているため、モーダルBのようにモーダルないが長い場合にモーダルの上下が切れてしまいます。
この対応策として、モーダルの高さが画面高さより高い場合、position: absolute;での配置になるようにしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
$(function() {
    // モーダルを開く
    $(document).on('click', '[data-modal-link]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalLink');
        modal_open(target);
    });
 
    // モーダルを閉じる
    $('.js-modalclose').on('click', function(e) {
        e.preventDefault();
        modal_close();
    });
 
  $(window).on('resize', function() {
    modal_position();
  });
});
 
// モーダルを開く
function modal_open(target) {
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    $('.modal-bg').addClass('is-show');
    modal_position();
}
 
// モーダルを閉じる
function modal_close() {
    $('[data-modal-content]').removeClass('is-show');
    $('.modal-bg').removeClass('is-show');
}
 
// モーダルの位置調整
function modal_position() {
    var $modal = $('[data-modal-content].is-show');
    if($modal.length) {
        var winH = $(window).height();
        var modalHeight = $modal.outerHeight();
        if(winH <= modalHeight) {
            var winSctop = $(window).scrollTop();
            $modal.css({
                position: 'absolute',
                top: winSctop + 10,
                transform: 'translateX(-50%)'
            });
        } else {
            $modal.removeAttr('style');
        }
    }
}

これでモーダル内が高い場合でも、スクロールですべて表示できるようになりました。
モーダルが長い場合のデモページ
 

モーダルを切り替える

モーダル内から別のモーダルに切り替えられるようにしてみます。
モーダル内に切り替え用のボタンを追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="modal-bg js-modalclose"></div>
<div class="modal" data-modal-content="modal-a">
  <p>モーダルAのコンテンツです。</p>
  <button data-modal-change="modal-b">モーダルBへ</button>
  <button class="js-modalclose">閉じる</button>
</div>
<!-- END modal-a -->
<div class="modal" data-modal-content="modal-b">
  <p>モーダルBのコンテンツです。</p>
  〜 略 〜
  <p>モーダルBのコンテンツです。</p>
  <button data-modal-change="modal-a">モーダルAへ</button>
  <button class="js-modalclose">閉じる</button>
</div>
<!-- END modal-b -->

ボタンにdata-modal-changeを設定して、値には開きたいモーダルを指定しています。

JavaScriptに切り替えの処理を追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
$(function() {
    // モーダルを開く
    $(document).on('click', '[data-modal-link]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalLink');
        modal_open(target);
    });
 
    // モーダルを切り替える
    $(document).on('click', '[data-modal-change]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalChange');
        modal_change(target);
    });
 
    // モーダルを閉じる
    $('.js-modalclose').on('click', function(e) {
        e.preventDefault();
        modal_close();
    });
 
  $(window).on('resize', function() {
    modal_position();
  });
});
 
// モーダルを開く
function modal_open(target) {
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    $('.modal-bg').addClass('is-show');
    modal_position();
}
 
// モーダルを切り替える
function modal_change(target) {
    $('[data-modal-content]').removeClass('is-show');
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    modal_position();
}
 
// モーダルを閉じる
function modal_close() {
    $('[data-modal-content]').removeClass('is-show');
    $('.modal-bg').removeClass('is-show');
}
 
// モーダルの位置調整
function modal_position() {
    var $modal = $('[data-modal-content].is-show');
    if($modal.length) {
        var winH = $(window).height();
        var modalHeight = $modal.outerHeight();
        if(winH <= modalHeight) {
            var winSctop = $(window).scrollTop();
            $modal.css({
                position: 'absolute',
                top: winSctop + 10,
                transform: 'translateX(-50%)'
            });
        } else {
            $modal.removeAttr('style');
        }
    }
}

別のモーダルに切り替えるデモページ
 

ページアクセス時にモーダルを表示する

特定のページからアクセスした場合にモーダルを表示するなどできるように、パラメータでモーダルを最初から開けるようにしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
$(function() {
    // タブのパラメータがついている時の対応
    var modalParam = get_modal_param();
    if($('[data-modal-content="' + modalParam + '"]').length > 0) {
        modal_open(modalParam);
    }
 
    // モーダルを開く
    $(document).on('click', '[data-modal-link]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalLink');
        modal_open(target);
    });
 
    // モーダルを切り替える
    $(document).on('click', '[data-modal-change]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalChange');
        modal_change(target);
    });
 
    // モーダルを閉じる
    $('.js-modalclose').on('click', function(e) {
        e.preventDefault();
        modal_close();
    });
 
  $(window).on('resize', function() {
    modal_position();
  });
});
 
// URLのパラメータ取得
function get_modal_param() {
    var params = [];
    var param = location.search.substring(1).split('&');
    for(var i = 0; i < param.length; i++) {
        params[i] = param[i].split('=');
    }
    for(var i = 0; i < params.length; i++) {
        if(params[i][0] === 'modal' &&  params[i][1] !== undefined) {
            return params[i][1];
        }
    }
    return false;
}
 
// モーダルを開く
function modal_open(target) {
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    $('.modal-bg').addClass('is-show');
    modal_position();
}
 
// モーダルを切り替える
function modal_change(target) {
    $('[data-modal-content]').removeClass('is-show');
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    modal_position();
}
 
// モーダルを閉じる
function modal_close() {
    $('[data-modal-content]').removeClass('is-show');
    $('.modal-bg').removeClass('is-show');
}
 
// モーダルの位置調整
function modal_position() {
    var $modal = $('[data-modal-content].is-show');
    if($modal.length) {
        var winH = $(window).height();
        var modalHeight = $modal.outerHeight();
        if(winH <= modalHeight) {
            var winSctop = $(window).scrollTop();
            $modal.css({
                position: 'absolute',
                top: winSctop + 10,
                transform: 'translateX(-50%)'
            });
        } else {
            $modal.removeAttr('style');
        }
    }
}

33〜46行目でURLのパラメータからモーダルの設定を取得して、4〜6行目で該当のモーダルを開いています。
パラメータでモーダルを開くデモページ
 

初回ページアクセス時のみモーダルを表示する

最後に初回アクセスのみモーダルを開くようにしてみます。
仕組み的には以前投稿している以下の記事と同じ内容です。
WebStorageで1回目のアクセス時のみモーダルを表示する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
$(function() {
    // 1回目のアクセスのみモーダルを表示
    var firstAccess = 'modal-a';
    if(sessionStorage.getItem(firstAccess) === null) {
        sessionStorage.setItem(firstAccess, 'on');
        modal_open(firstAccess);
    }
 
    // タブのパラメータがついている時の対応
    var modalParam = get_modal_param();
    if($('[data-modal-content="' + modalParam + '"]').length > 0) {
        modal_open(modalParam);
    }
 
    // モーダルを開く
    $(document).on('click', '[data-modal-link]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalLink');
        modal_open(target);
    });
 
    // モーダルを切り替える
    $(document).on('click', '[data-modal-change]', function(e) {
        e.preventDefault();
        var target = $(this).data('modalChange');
        modal_change(target);
    });
 
    // モーダルを閉じる
    $('.js-modalclose').on('click', function(e) {
        e.preventDefault();
        modal_close();
    });
 
  $(window).on('resize', function() {
    modal_position();
  });
});
 
// URLのパラメータ取得
function get_modal_param() {
    var params = [];
    var param = location.search.substring(1).split('&');
    for(var i = 0; i < param.length; i++) {
        params[i] = param[i].split('=');
    }
    for(var i = 0; i < params.length; i++) {
        if(params[i][0] === 'modal' &&  params[i][1] !== undefined) {
            return params[i][1];
        }
    }
    return false;
}
 
// モーダルを開く
function modal_open(target) {
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    $('.modal-bg').addClass('is-show');
    modal_position();
}
 
// モーダルを切り替える
function modal_change(target) {
    $('[data-modal-content]').removeClass('is-show');
    $('[data-modal-content = ' + target + ']').addClass('is-show');
    modal_position();
}
 
// モーダルを閉じる
function modal_close() {
    $('[data-modal-content]').removeClass('is-show');
    $('.modal-bg').removeClass('is-show');
}
 
// モーダルの位置調整
function modal_position() {
    var $modal = $('[data-modal-content].is-show');
    if($modal.length) {
        var winH = $(window).height();
        var modalHeight = $modal.outerHeight();
        if(winH <= modalHeight) {
            var winSctop = $(window).scrollTop();
            $modal.css({
                position: 'absolute',
                top: winSctop + 10,
                transform: 'translateX(-50%)'
            });
        } else {
            $modal.removeAttr('style');
        }
    }
}

3行目で開くモーダルを指定しています。
これで初回アクセスのみモーダルを開けくようになりました。
初回表示のみモーダルを表示するデモページ
 

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2025年3月
 1
2345678
9101112131415
16171819202122
23242526272829
3031