2016.10.05

【CSS , jQuery】スクロールに対応したモーダルウィンドウを実装するサンプル

Category: css / js

Tags, , , ,

スクロールに対応したモーダルウィンドウを実装するサンプルです。
レスポンシブにも対応しています。

以下のモーダルを開くボタンとモーダルウィンドウのソースを任意の場所に設置します。

html

<p><a href="" id="modal-open">モーダルを開く</a></p>
<div class="modal" id="modal">
<div class="modal-wrap">
<div class="modal-content">
<div class="modal-table-wrap">
<div class="modal-table-cell">
<div class="modal-content-box">
<div class="modal-content-inner">
<p class="modal-btn-close" id="modal-btn-close">
<span class="bar01"></span>
<span class="bar02"></span>
</p>
<div class="modal-ct-text-box">
<!-- ここにコンテンツ -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

css/sass

sass / compass

.modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999999;
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#80000000,endColorstr=#80000000); 
background: rgba(0, 0, 0, .5);
}
.modal-wrap {
height: 100%;
padding: 0 30px;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.modal-content {
height: 100%;
max-width: 960px;
margin: 0 auto;
}
.modal-table-wrap {
display: table;
table-layout: fixed;
height: 100%;
width: 100%;
}
.modal-table-cell {
display: table-cell;
padding: 60px 0 60px;
vertical-align: middle;
}
.modal-content-box {
position: relative;
margin: 0 auto;
background: #fff;
}
.modal-content-inner {
padding: 50px 30px 50px;
}
.modal-btn-close {
position: absolute;
top: -40px;
right: 0;
z-index: 9;
height: 30px;
width: 30px;
cursor: pointer;
span {
display: block;
background: #fff;
height: 2px;
width: 30px;
}
.bar01 {
@include transform(translateY(15px) rotate(-45deg));
}
.bar02 {
@include transform(translateY(13px) rotate(45deg));
}
}
@media only screen and (max-width: 768px) {
.modal-wrap {
padding: 0 10px/320px*100%;
}
.modal-content-inner {
padding: 40px 10px/300px*100% 40px;
}
}

css

.modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999999;
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#80000000,endColorstr=#80000000); 
background: rgba(0, 0, 0, 0.5);
}
.modal-wrap {
height: 100%;
padding: 0 30px;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.modal-content {
height: 100%;
max-width: 960px;
margin: 0 auto;
}
.modal-table-wrap {
display: table;
table-layout: fixed;
height: 100%;
width: 100%;
}
.modal-table-cell {
display: table-cell;
padding: 60px 0 60px;
vertical-align: middle;
}
.modal-content-box {
position: relative;
margin: 0 auto;
background: #fff;
}
.modal-content-inner {
padding: 50px 30px 50px;
}
.modal-btn-close {
position: absolute;
top: -40px;
right: 0;
z-index: 9;
height: 30px;
width: 30px;
cursor: pointer;
}
.modal-btn-close span {
display: block;
background: #fff;
height: 2px;
width: 30px;
}
.modal-btn-close .bar01 {
-moz-transform: translateY(15px) rotate(-45deg);
-ms-transform: translateY(15px) rotate(-45deg);
-webkit-transform: translateY(15px) rotate(-45deg);
transform: translateY(15px) rotate(-45deg);
}
.modal-btn-close .bar02 {
-moz-transform: translateY(13px) rotate(45deg);
-ms-transform: translateY(13px) rotate(45deg);
-webkit-transform: translateY(13px) rotate(45deg);
transform: translateY(13px) rotate(45deg);
}
@media only screen and (max-width: 768px) {
.modal-wrap {
padding: 0 3.125%;
}
.modal-content-inner {
padding: 40px 3.33333% 40px;
}
}

js

//モーダル
jQuery(document).ready(function($){
//モーダル表示判別フラグ
var modal_show_flg = false;
var modal = $('#modal');
//モーダルオープン
$('#modal-open').click(function(e){
e.preventDefault();
modal.fadeIn();
bodyFix();
setTimeout(function() {
modal_show_flg = true;
}, 10);
});
//モーダルクローズ
$('#modal-btn-close').click(function(){
modalClose();
});
$(document).click(function(e) {
var target = $(e.target);
if(modal_show_flg === true && !target.parents('.modal-content-box').length) {
modalClose();
return false;
}
if(modal_show_flg === true && target.hasClass('modal-content-box')) {
modalClose();
return false;
}
});
//モーダルクローズ関数
function modalClose() {
bodyFixReset();
modal.fadeOut();
modal_show_flg = false;
}
//body固定関数
var bodyElm = $('body');
var scrollPosi;
function bodyFix() {
scrollPosi = $(window).scrollTop();
bodyElm.css({
'position': 'fixed',
'width': '100%',
'z-index': '1',
'top': -scrollPosi
});
}
//body fixリセット
function bodyFixReset() {
bodyElm.removeAttr('style');
//scroll位置を調整
$("html, body").scrollTop(scrollPosi);
}
});

上記のコードではモーダルを開いた時に、背景のメインコンテンツのスクロールを禁止しています。

スクロール禁止を解除する場合は、以下のようにbody固定関数を取り除きます。

//モーダル
jQuery(document).ready(function($){
//モーダル表示判別フラグ
var modal_show_flg = false;
var modal = $('#modal');
//モーダルオープン
$('#modal-open').click(function(e){
e.preventDefault();
modal.fadeIn();
setTimeout(function() {
modal_show_flg = true;
}, 10);
});
//モーダルクローズ
$('#modal-btn-close').click(function(){
modalClose();
});
$(document).click(function(e) {
var target = $(e.target);
if(modal_show_flg === true && !target.parents('.modal-content-box').length) {
modalClose();
return false;
}
if(modal_show_flg === true && target.hasClass('modal-content-box')) {
modalClose();
return false;
}
});
//モーダルクローズ関数
function modalClose() {
modal.fadeOut();
modal_show_flg = false;
}
});

モーダルウィンドウの中央寄せを display: table; にて実装しているため、タグの階層は深めですが、IE8など古いブラウザまで幅広く表示を維持できると思います。

関連リンク

Category : css / js