【jQuery】プラグインを使わずにモーダルを作ってみる
- 2021.7.27
- jQuery


プラグインを使わずにモーダルってできますか?

ふむふむ、やってみましょうー
1.プラグインを使わないモーダルのサンプル
スマホでも問題ない。
IEでも問題ない。
完成ですー。
See the Pen
【jQuery】プラグインを使わずにモーダルを作ってみる by 125naroom (@125naroom)
on CodePen.
コードはこちら
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
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
$(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); } } } });
2.プラグインを使わないモーダルのサンプル(同じページに複数設置)
『data-modal-org-target』と『id』の紐付けさえ間違えなければ簡単ですねー。
See the Pen
【jQuery】プラグインを使わずにモーダルを作ってみる、複数も可能 by 125naroom (@125naroom)
on CodePen.
コードはこちら
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
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
$(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の日本語リファレンスサイトがあるので一度チェックしてみるといろいろ解決できたりしますよ。
さいごに

わー、これこれー!

デバイス対応が難しかったですねー
さ、おやつにしましょうー
さ、おやつにしましょうー
関連記事
おすすめ
かんれん
- web / 2019.12.19
- 【CSS】背景画像を固定したおしゃれなLP(ランディングページ)を作ってみよう
- web / 2019.7.19
- 【CSS】olのリストで①、②、③(丸数字)を表示させる
- web / 2023.2.23
- 【CSS】『shape-outside』でテキストの回り込みを円形にしてみる
Googleさんのおすすめ
人気記事
- web / 2019.4.16
- 【CSS】ハンバーガーメニュー実装サンプル集(クリック時のエフェクトも集めました)
- web / 2022.2.1
- 【jQuery】アコーディオン実装サンプル10選
- web / 2019.9.27
- 【jQuery】スライダープラグイン「slick」実装サンプル集
Googleさんのおすすめ
デザインの記事
- 2023.10.02New
- Aubloom オーブルーム – RAWSILK SHAMPOO ローシルクシャンプー
- 国内、海外のウェブデザイン、パソコン・タブレット・スマートフォンでも見やすいレスポンシブ対応の「あ、いいな」と思うウェブデザインを集めています。
- デザインのこと – Web design gallery
- 2022.06.15
- ちょっと思い出しただけ
- (C)2022『ちょっと思い出しただけ』製作委員会 もくじ 『ちょっと思い出しただけ』 あ…
- いつかのこと – 無印良品の家と暮らす
- 2023.07.31
- 【Google Chrome】ショートカットキーまとめ(Windows or Mac)
- クロームでF5(更新)ってどうするんでしたっけ? あー、Macですか?わかるわかる、な…
- 125naroom / デザインするところ(会社)です。