汎用的に流用できるような、簡易なモーダルを作成してみます。
サンプルコード
まずはモーダルを開くリンク部分です。
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行目で開くモーダルを指定しています。
これで初回アクセスのみモーダルを開けくようになりました。
初回表示のみモーダルを表示するデモページ
コメントが承認されるまで時間がかかります。