汎用的に流用できるような、簡易なモーダルを作成してみます。
サンプルコード
まずはモーダルを開くリンク部分です。
data属性で開くモーダルを設定するようにします。
<a href="" data-modal-link="modal-a">モーダルAを開く</a> <a href="" data-modal-link="modal-b">モーダルBを開く</a>
data-modal-linkにモーダル名を指定してください。
次にモーダル部分です。
モーダルの要素にdata-modal-contentを設定して、先ほどリンクに設定したモーダル名を入れます。
<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です。
.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です。
$(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;での配置になるようにしてみます。
$(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'); } } }
これでモーダル内が高い場合でも、スクロールですべて表示できるようになりました。
モーダルが長い場合のデモページ
モーダルを切り替える
モーダル内から別のモーダルに切り替えられるようにしてみます。
モーダル内に切り替え用のボタンを追加します。
<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に切り替えの処理を追加します。
$(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'); } } }
ページアクセス時にモーダルを表示する
特定のページからアクセスした場合にモーダルを表示するなどできるように、パラメータでモーダルを最初から開けるようにしてみます。
$(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回目のアクセス時のみモーダルを表示する
$(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行目で開くモーダルを指定しています。
これで初回アクセスのみモーダルを開けくようになりました。
初回表示のみモーダルを表示するデモページ
コメントが承認されるまで時間がかかります。