プラグインを使わないモーダルのサンプル
スマホでも問題ない。
IEでも問題ない。
完成ですー。
See the Pen 【jQuery】プラグインを使わずにモーダルを作ってみる by 125naroom (@125naroom) on CodePen.
HTMLとCSSとjQueryはこちら
HTML
<div class="s_section gutter">
<a href="#modal-a" data-modal-org-target="#modal-a" class="_a">モーダルへ</a>
</div>
<div class="a-modal-org" role="dialog" id="modal-a">
<div class="a-modal-org__inner">
<div class="a-modal-org__inner2">
<div class="a-modal-org__inner3">
<div class="a-modal-org__body">
<div class="a-modal-org__scroll gutter">
ここに内容
</div>
</div>
</div>
<div class="a-modal-org__close"><a class="a-modal-org__btn" href="#"><span class="a-modal-org__btn-inner"></span><span class="a-display-off">閉じる</span></a></div>
</div>
</div>
</div>
<div class="a-modal-org-overlay" tabindex="0"></div>
CSS
/*=========
project - modal-org
=========*/
.a-modal-org {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 190002;
}
.a-modal-org__inner {
display: flex;
align-items: center;
margin: 0 auto;
height: 100%;
}
@media print, screen and (min-width: 737px) {
.a-modal-org__inner {
width: 80vw;
max-width: 900px;
}
}
@media screen and (max-width: 736px) {
.a-modal-org__inner {
width: 85vw;
}
}
.a-modal-org__inner2 {
position: relative;
width: 100%;
}
.a-modal-org__inner3 {
background-color: #ffffff;
}
@media print, screen and (min-width: 769px) {
.a-modal-org__inner3 {
max-height: 80vh;
border-radius: 12px;
border: 1.5rem solid #fff;
}
}
@media print, screen and (max-width: 768px) {
.a-modal-org__inner3 {
max-height: 70vh;
border-radius: 6px;
border: 1.125rem solid #fff;
}
}
.a-modal-org__body {
position: relative;
overflow: hidden;
box-sizing: border-box;
}
.a-modal-org__scroll.is-scroll {
overflow-y: scroll;
}
@media print, screen and (min-width: 769px) {
.a-modal-org__scroll.is-scroll {
padding-right: 0.5rem;
}
}
.a-modal-org__close {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
}
.a-modal-org__btn {
box-sizing: border-box;
background-color: #333333;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
.a-modal-org__btn-inner {
display: inline-block;
box-sizing: border-box;
width: 20px;
height: 20px;
position: relative;
}
.a-modal-org__btn-inner::before, .a-modal-org__btn-inner::after {
position: absolute;
content: "";
margin: auto;
box-sizing: border-box;
vertical-align: middle;
}
.a-modal-org__btn-inner::before {
border-top: 2px solid #ffffff;
width: 20px;
height: 0;
top: 0;
bottom: 0;
left: 0;
transform: rotate(45deg);
}
.a-modal-org__btn-inner::after {
border-left: 2px solid #ffffff;
width: 0;
height: 20px;
top: 0;
bottom: 0;
left: 9px;
transform: rotate(45deg);
}
/*=========
utility - display-off
=========*/
.a-display-off {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
border: 0;
overflow: hidden;
padding: 0;
clip: rect(0, 0, 0, 0);
}
/*=========
layout - a-modal-org-overlay
=========*/
.a-modal-org-overlay {
display: none;
z-index: 190001;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.7);
}
jQuery
$(function(){
// ============
// a処理を一旦リセット
// ============
$('a[data-modal-org-target]').off('click');
// ============
// U a-modal-org
// ============
if($('.a-modal-org').length){
var overlay = $('.a-modal-org-overlay');
$('[data-modal-org-target]').each(function (){
var modalTarget = $($(this).attr('data-modal-org-target'));
var modalTargetinner3 = modalTarget.find('.a-modal-org__inner3');
var modalTargetHead = modalTarget.find('.a-modal-org__head');
var modalTargetBody = modalTarget.find('.a-modal-org__body');
var modalTargetFoot = modalTarget.find('.a-modal-org__foot');
var modalTargetScroll = modalTarget.find('.a-modal-org__scroll');
var modalTargetBtn = modalTarget.find('.a-modal-org__btn');
if(modalTarget){
$(this).on('click',function(){
modal_org_open();
if(overlay){
overlay.on('click focusin',function(){
modal_org_close();
return false;
});
}
return false;
});
modalTarget.on('click',function(){
modal_org_close();
});
modalTargetinner3.on('click',function(){
event.stopPropagation();
});
modalTargetBtn.on('click',function(){
modal_org_close();
return false;
});
}
// モーダルの高さ監視
function modal_org_height(){
if (modalTarget.is(':visible')) {
modalTargetBody.css("max-height", "none");
modalTargetScroll.removeClass('is-scroll').css("max-height", "none");
var outerHeight = modalTargetinner3.innerHeight();
if(modalTargetHead.length) outerHeight = outerHeight - modalTargetHead.outerHeight();
if(modalTargetFoot.length) outerHeight = outerHeight - modalTargetFoot.outerHeight();
modalTargetBody.css("max-height", outerHeight);
var scrollHeight = Math.floor(modalTargetScroll.outerHeight());
if(outerHeight < scrollHeight){
modalTargetScroll.addClass('is-scroll').css("max-height", outerHeight);
}
}
}
$(window).on('resize',function(){
modal_org_height();
});
function modal_org_open(){
scroll_lock();
// モーダルチェック
modalTarget.css('opacity','0').show();
modalTargetScroll.scrollTop(0);
modal_org_height();
modalTarget.hide().css('opacity','1');
// モーダル表示
modalTarget.fadeIn(600, function(){
$(this).attr('aria-expanded', 'true');
});
modalTarget.attr('tabindex',1).focus().attr('tabindex','');
// if(overlay) overlay.fadeIn(200);
if(overlay) a_modal_org_overlay(true, 200); // a-modal-org-overlay用
}
function modal_org_close(){
scroll_lock_off();
modalTarget.attr('aria-expanded', 'false').fadeOut();
// if(overlay) overlay.off().fadeOut();
if(overlay) a_modal_org_overlay(false, 'fast'); // a-modal-org-overlay用
}
});
}
// ============
// U scroll_lock
// ============
var uA = navigator.userAgent;
var os = osCh(); //iOS,ipadOS,Android,Mac,Win
function osCh(){
if (uA.indexOf('iPhone') > -1 || uA.indexOf('iPod') > -1 || uA.indexOf('iPad') > -1) return "iOS";
if (uA.indexOf('Android') > -1) return "Android";
if (uA.indexOf("Mac") != -1 && !('ontouchend' in document)) return "Mac";
if (uA.indexOf("Mac") != -1 && 'ontouchend' in document) return "ipadOS"; // safari only
if (uA.indexOf("Win") != -1) return "Win";
return "unknown";
}
var scrollPosition;
function scroll_lock(){
if( os == "iOS" || os == "ipadOS" ){
scrollPosition = $(window).scrollTop();
$('body').addClass('is-scroll-lock').css({'top': -scrollPosition});
}else{
var clientWidth = $(window).innerWidth();
var noScrollBarWidth = $(window).outerWidth();
$('body').css({'overflow': 'hidden'});
diff = noScrollBarWidth - clientWidth;
if(diff > 0){
$('body').css({'padding-right': diff + 'px'});
// if(headerFixedItem && $('[data-header-fixed="true"]').length) headerFixedItem.css({'padding-right': diff + 'px'});
};
}
}
function scroll_lock_off(){
if( os == "iOS" || os == "ipadOS" ){
$('body').removeClass('is-scroll-lock').css({'top': 0});
window.scrollTo( 0 , scrollPosition );
}else{
$('body').css({'overflow': 'auto'});
$('body').css({'padding-right': '0'});
// if(headerFixedItem) headerFixedItem.css({'padding-right': 0});
}
}
// ============
// U a-modal-org-overlay
// ============
function a_modal_org_overlay(flag,speed){
var overlay = $('.a-modal-org-overlay');
if(overlay.length){
if(flag){
overlay.stop().fadeIn(speed);
}else{
overlay.stop().off().fadeOut(speed);
}
}
}
});
プラグインを使わないモーダルのサンプル(同じページに複数設置)
『data-modal-org-target』と『id』の紐付けさえ間違えなければ簡単ですねー。
See the Pen 【jQuery】プラグインを使わずにモーダルを作ってみる、複数も可能 by 125naroom (@125naroom) on CodePen.
HTMLとCSSとjQueryはこちら
HTML
<div class="s_section gutter">
<a href="#modal-a" data-modal-org-target="#modal-a" class="_a">モーダルAへ</a>
<a href="#modal-b" data-modal-org-target="#modal-b" class="_a">モーダルBへ</a>
<a href="#modal-c" data-modal-org-target="#modal-c" class="_a">モーダルCへ</a>
</div>
<div class="a-modal-org" role="dialog" id="modal-a">
<div class="a-modal-org__inner">
<div class="a-modal-org__inner2">
<div class="a-modal-org__inner3">
<div class="a-modal-org__body">
<div class="a-modal-org__scroll">
モーダルAの内容
</div>
</div>
</div>
<div class="a-modal-org__close"><a class="a-modal-org__btn" href="#"><span class="a-modal-org__btn-inner"></span><span class="a-display-off">閉じる</span></a></div>
</div>
</div>
</div>
<div class="a-modal-org" role="dialog" id="modal-b">
<div class="a-modal-org__inner">
<div class="a-modal-org__inner2">
<div class="a-modal-org__inner3">
<div class="a-modal-org__body">
<div class="a-modal-org__scroll">
モーダルBの内容
</div>
</div>
</div>
<div class="a-modal-org__close"><a class="a-modal-org__btn" href="#"><span class="a-modal-org__btn-inner"></span><span class="a-display-off">閉じる</span></a></div>
</div>
</div>
</div>
<div class="a-modal-org" role="dialog" id="modal-c">
<div class="a-modal-org__inner">
<div class="a-modal-org__inner2">
<div class="a-modal-org__inner3">
<div class="a-modal-org__body">
<div class="a-modal-org__scroll">
モーダルCの内容
</div>
</div>
</div>
<div class="a-modal-org__close"><a class="a-modal-org__btn" href="#"><span class="a-modal-org__btn-inner"></span><span class="a-display-off">閉じる</span></a></div>
</div>
</div>
</div>
<div class="a-modal-org-overlay" tabindex="0"></div>
CSS
/*=========
project - modal-org
=========*/
.a-modal-org {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 190002;
}
.a-modal-org__inner {
display: flex;
align-items: center;
margin: 0 auto;
height: 100%;
}
@media print, screen and (min-width: 737px) {
.a-modal-org__inner {
width: 80vw;
max-width: 900px;
}
}
@media screen and (max-width: 736px) {
.a-modal-org__inner {
width: 85vw;
}
}
.a-modal-org__inner2 {
position: relative;
width: 100%;
}
.a-modal-org__inner3 {
background-color: #ffffff;
}
@media print, screen and (min-width: 769px) {
.a-modal-org__inner3 {
max-height: 80vh;
border-radius: 12px;
border: 1.5rem solid #fff;
}
}
@media print, screen and (max-width: 768px) {
.a-modal-org__inner3 {
max-height: 70vh;
border-radius: 6px;
border: 1.125rem solid #fff;
}
}
.a-modal-org__body {
position: relative;
overflow: hidden;
box-sizing: border-box;
}
.a-modal-org__scroll.is-scroll {
overflow-y: scroll;
}
@media print, screen and (min-width: 769px) {
.a-modal-org__scroll.is-scroll {
padding-right: 0.5rem;
}
}
.a-modal-org__close {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
}
.a-modal-org__btn {
box-sizing: border-box;
background-color: #333333;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
.a-modal-org__btn-inner {
display: inline-block;
box-sizing: border-box;
width: 20px;
height: 20px;
position: relative;
}
.a-modal-org__btn-inner::before, .a-modal-org__btn-inner::after {
position: absolute;
content: "";
margin: auto;
box-sizing: border-box;
vertical-align: middle;
}
.a-modal-org__btn-inner::before {
border-top: 2px solid #ffffff;
width: 20px;
height: 0;
top: 0;
bottom: 0;
left: 0;
transform: rotate(45deg);
}
.a-modal-org__btn-inner::after {
border-left: 2px solid #ffffff;
width: 0;
height: 20px;
top: 0;
bottom: 0;
left: 9px;
transform: rotate(45deg);
}
/*=========
utility - display-off
=========*/
.a-display-off {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
border: 0;
overflow: hidden;
padding: 0;
clip: rect(0, 0, 0, 0);
}
/*=========
layout - a-modal-org-overlay
=========*/
.a-modal-org-overlay {
display: none;
z-index: 190001;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.7);
}
jQuery
$(function(){
// ============
// a処理を一旦リセット
// ============
$('a[data-modal-org-target]').off('click');
// ============
// U a-modal-org
// ============
if($('.a-modal-org').length){
var overlay = $('.a-modal-org-overlay');
$('[data-modal-org-target]').each(function (){
var modalTarget = $($(this).attr('data-modal-org-target'));
var modalTargetinner3 = modalTarget.find('.a-modal-org__inner3');
var modalTargetHead = modalTarget.find('.a-modal-org__head');
var modalTargetBody = modalTarget.find('.a-modal-org__body');
var modalTargetFoot = modalTarget.find('.a-modal-org__foot');
var modalTargetScroll = modalTarget.find('.a-modal-org__scroll');
var modalTargetBtn = modalTarget.find('.a-modal-org__btn');
if(modalTarget){
$(this).on('click',function(){
modal_org_open();
if(overlay){
overlay.on('click focusin',function(){
modal_org_close();
return false;
});
}
return false;
});
modalTarget.on('click',function(){
modal_org_close();
});
modalTargetinner3.on('click',function(){
event.stopPropagation();
});
modalTargetBtn.on('click',function(){
modal_org_close();
return false;
});
}
// モーダルの高さ監視
function modal_org_height(){
if (modalTarget.is(':visible')) {
modalTargetBody.css("max-height", "none");
modalTargetScroll.removeClass('is-scroll').css("max-height", "none");
var outerHeight = modalTargetinner3.innerHeight();
if(modalTargetHead.length) outerHeight = outerHeight - modalTargetHead.outerHeight();
if(modalTargetFoot.length) outerHeight = outerHeight - modalTargetFoot.outerHeight();
modalTargetBody.css("max-height", outerHeight);
var scrollHeight = Math.floor(modalTargetScroll.outerHeight());
if(outerHeight < scrollHeight){
modalTargetScroll.addClass('is-scroll').css("max-height", outerHeight);
}
}
}
$(window).on('resize',function(){
modal_org_height();
});
function modal_org_open(){
scroll_lock();
// モーダルチェック
modalTarget.css('opacity','0').show();
modalTargetScroll.scrollTop(0);
modal_org_height();
modalTarget.hide().css('opacity','1');
// モーダル表示
modalTarget.fadeIn(600, function(){
$(this).attr('aria-expanded', 'true');
});
modalTarget.attr('tabindex',1).focus().attr('tabindex','');
// if(overlay) overlay.fadeIn(200);
if(overlay) a_modal_org_overlay(true, 200); // a-modal-org-overlay用
}
function modal_org_close(){
scroll_lock_off();
modalTarget.attr('aria-expanded', 'false').fadeOut();
// if(overlay) overlay.off().fadeOut();
if(overlay) a_modal_org_overlay(false, 'fast'); // a-modal-org-overlay用
}
});
}
// ============
// U scroll_lock
// ============
var uA = navigator.userAgent;
var os = osCh(); //iOS,ipadOS,Android,Mac,Win
function osCh(){
if (uA.indexOf('iPhone') > -1 || uA.indexOf('iPod') > -1 || uA.indexOf('iPad') > -1) return "iOS";
if (uA.indexOf('Android') > -1) return "Android";
if (uA.indexOf("Mac") != -1 && !('ontouchend' in document)) return "Mac";
if (uA.indexOf("Mac") != -1 && 'ontouchend' in document) return "ipadOS"; // safari only
if (uA.indexOf("Win") != -1) return "Win";
return "unknown";
}
var scrollPosition;
function scroll_lock(){
if( os == "iOS" || os == "ipadOS" ){
scrollPosition = $(window).scrollTop();
$('body').addClass('is-scroll-lock').css({'top': -scrollPosition});
}else{
var clientWidth = $(window).innerWidth();
var noScrollBarWidth = $(window).outerWidth();
$('body').css({'overflow': 'hidden'});
diff = noScrollBarWidth - clientWidth;
if(diff > 0){
$('body').css({'padding-right': diff + 'px'});
// if(headerFixedItem && $('[data-header-fixed="true"]').length) headerFixedItem.css({'padding-right': diff + 'px'});
};
}
}
function scroll_lock_off(){
if( os == "iOS" || os == "ipadOS" ){
$('body').removeClass('is-scroll-lock').css({'top': 0});
window.scrollTo( 0 , scrollPosition );
}else{
$('body').css({'overflow': 'auto'});
$('body').css({'padding-right': '0'});
// if(headerFixedItem) headerFixedItem.css({'padding-right': 0});
}
}
// ============
// U a-modal-org-overlay
// ============
function a_modal_org_overlay(flag,speed){
var overlay = $('.a-modal-org-overlay');
if(overlay.length){
if(flag){
overlay.stop().fadeIn(speed);
}else{
overlay.stop().off().fadeOut(speed);
}
}
}
});
メモ
jQueryのことで何かわからないことがあればjQueryの日本語リファレンスサイトがあるので一度チェックしてみるといろいろ解決できたりしますよ。