モーダルウィンドウ
モーダルウィンドウを実装するjQueryプラグインはたくさんありますが、わざわざプラグインを使わなくても、意外と簡単にモーダルウィンドウを実装することができます。
モーダルウィンドウとは?
素材サイトなどを見ているとよく出てくる、会員登録を促す画像やボタンが全画面にオーバーレイして表示されるやつです。モーダルウィンドウが表示されると、閉じるか、指定の動作を完了するまで他の操作ができないところが特徴で、この点がメリットでもあり、デメリットでもあります。
メリット
ユーザーに見せたい情報だけを見せることができます。また、モーダルウィンドウを閉じない限りは表示されるので、行動を制限することができます。
デメリット
メリットがそのままデメリットになります。画面全体を覆い、閉じるまで他の作業ができないというのは、ユーザビリティ上よくありません。
モーダルウィンドウの基本
1 2 3 4 5 6 7 8 9 10 11 12 |
<body> <div class="content"> <a class="js-modal-open" href="">クリックでモーダルを表示</a> </div> <div class="modal js-modal"> <div class="modal__bg js-modal-close"></div> <div class="modal__content"> <p>ここにモーダルウィンドウで表示したいコンテンツを入れます。モーダルウィンドウを閉じる場合は下の「閉じる」をクリックするか、背景の黒い部分をクリックしても閉じることができます。</p> <a class="js-modal-close" href="">閉じる</a> </div><!--modal__inner--> </div><!--modal--> </body> |
3行目
a要素「js-modal-open」をクリックしたらモーダルウィンドウが表示されるように、この後のjQueryで処理していきます。
5行目
「modal」がモーダルウィンドウ全体の部分になります。
6行目
モーダルウィンドウを表示している時に背景をクリックしてもモーダルウィンドウを閉じられるように、クリック用の空の背景要素として「modal__bg」を「modal」の中に入れています。
7行目
「modal__content」の中にモーダルウィンドウで表示したいコンテンツを入れます。
クラス名の頭に「js-」と付けているものがありますが、こちらはこの後のjQueryで操作するクラスになります。
こうしておくことで、後で見た時や、他の人が見てもすぐにjQueryで操作しているということがわかります。
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
*{ box-sizing: border-box; margin: 0; padding: 0; } .content{ margin: 0 auto; padding: 40px; } .modal{ display: none; height: 100vh; position: fixed; top: 0; width: 100%; } .modal__bg{ background: rgba(0,0,0,0.8); height: 100vh; position: absolute; width: 100%; } .modal__content{ background: #fff; left: 50%; padding: 40px; position: absolute; top: 50%; transform: translate(-50%,-50%); width: 60%; } |
11行目
モーダルウィンドウ全体をラップする「modal」は、jQueryで表示・非表示を操作するので、初期状態は「display: none」にしておきます。
12行目
モーダルウィンドウの高さをブラウザの高さと合わせるため「height: 100vh」を指定しています。
ちなみに「ボックスの高さをブラウザの高さと合わせる」テクニックは下記の記事に詳しい内容があるので、興味があれば見てみてくださいね。
13行目
「position: abusolute」ではスクロールした際にモーダルウィンドウもスクロールされて見えなくなってしまうので「position: fixed」にして、固定表示にします。
18〜21行目
先ほどHTMLのところで書いたとおり、モーダルウィンドウを閉じるための背景要素になります。こちらもブラウザの高さと幅に合わせています。
親要素の「modal」に「position: fixed」が指定されているので、こちらは「position: absolute」でオッケーです。
また、モーダルウィンドウがオーバレイしてることがわかりやすいように、背景色は「rgba」で半透明にしています。
25,27,28,29行目
モーダルウィンドウのコンテンツを画面の縦横センターに配置している部分になります。
いくつか他のサンプルも見てきましたが、jQueryでコンテンツの幅を取得してやっていたいりしていましたが、そんなことをしなくてもこの4行で画面の縦横センターに配置することができます。
センター配置の仕組み
「position: absolute」を指定した上で、「left: 50%」と「top: 50%」を指定すると、ボックスの左上が親要素の縦横センターになります。
そして、さらに「transform: translate(-50%,-50%)」とすると、「left: 50%」と「top: 50%」は親要素の幅と高さに対して50%移動しますが、「transform」は自分の幅と高さに対しての50%移動します。よって下のイメージのように画面の縦横センターに配置することができます。
jQuery
1 2 3 4 5 6 7 8 9 10 |
$(function(){ $('.js-modal-open').on('click',function(){ $('.js-modal').fadeIn(); return false; }); $('.js-modal-close').on('click',function(){ $('.js-modal').fadeOut(); return false; }); }); |
jQueryは簡単です。「js-modal-open」をクリックしたら「fadeIn」でモーダルウィンドウを表示し、「js-modal-close」をクリックしたら「fadeOut」で非表示にしています。
4,8行目
a要素の場合は「return false」を書かないと、リンク要素として処理され、jQueryの処理ができないので注意しましょう。
応用編
ベースのモーダルウィンドウはそれほど難しくなかったと思います。ここからはせっかくなので、いくつか応用編をやっていきたいと思います。
応用編と言っても、対して高度なことはやらないので、ここまでできた方なら問題ないと思いますので、ぜひ最後まで見ていってください。
複数のモーダル
さて、ベースのモーダルウィンドウは1つだけだったのであれでよかったですが、表示したいモーダルが複数になるとこれまでのやり方ではダメなので、改良していきます。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<body> <div class="content"> <a class="js-modal-open" href="" data-target="modal01">クリックでモーダル1を表示</a><br> <a class="js-modal-open" href="" data-target="modal02">クリックでモーダル2を表示</a> </div> <div id="modal01" class="modal js-modal"> <div class="modal__bg js-modal-close"></div> <div class="modal__content"> <p>1つ目モーダルウィンドウです。ここにモーダルウィンドウで表示したいコンテンツを入れます。モーダルウィンドウを閉じる場合は下の「閉じる」をクリックするか、背景の黒い部分をクリックしても閉じることができます。</p> <a class="js-modal-close" href="">閉じる</a> </div><!--modal__inner--> </div><!--modal--> <div id="modal02" class="modal js-modal"> <div class="modal__bg js-modal-close"></div> <div class="modal__content"> <p>2つ目モーダルウィンドウです。ここにモーダルウィンドウで表示したいコンテンツを入れます。モーダルウィンドウを閉じる場合は下の「閉じる」をクリックするか、背景の黒い部分をクリックしても閉じることができます。</p> <a class="js-modal-close" href="">閉じる</a> </div><!--modal__inner--> </div><!--modal--> </body> |
3,4行目
a要素「js-modal-open」に「data-target」属性を追加しました。この値をモーダルウィンドウのID属性とリンクさせることで、どのモーダルウィンドウを開くかわかるようにしています。
6,13行目
前述のとおり、どのモーダルウィンドウかわかるようにID属性を追加しました。
CSS
CSSは変化なしです。
jQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$(function(){ $('.js-modal-open').each(function(){ $(this).on('click',function(){ var target = $(this).data('target'); var modal = document.getElementById(target); $(modal).fadeIn(); return false; }); }); $('.js-modal-close').on('click',function(){ $('.js-modal').fadeOut(); return false; }); }); |
jQueryはモーダルウィンドウを開く処理の方だけ変更しました。
2行目
「js-modal-open」が複数になったので、「each」メソッドの中で「this」を使うことで、どの「js-modal-open」がクリックされたかわかるようにします。
4行目
そして「data」メソッドで、クリックした「js-modal-open」の「data-target」属性を取得し、変数「target」に代入しています。
5行目
「data-target」の値はモーダルウィンドウのID属性とリンクさせているので、「document.getElementById(target)」とすることで、モーダルウィンドウが複数あっても表示したいものだけ取得することができます。
スクロール位置を元に戻す
モーダルウィンドウを表示している最中にスクロールしてしまった場合、表示した位置と閉じた時の位置が違うと、ユーザーが戸惑う可能性があります。ですので、モーダルウィンドウを閉じたら、表示したスクロールの位置に戻すようにしたいと思います。
モーダルウィンドウを表示したままスクロールして閉じても、開いた時のスクロール位置に戻ります。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<body> <div class="content"> <a class="js-modal-open" href="" data-target="modal01">クリックでモーダル1を表示</a><br> <a class="js-modal-open" href="" data-target="modal02">クリックでモーダル2を表示</a><br> <br> <div class="box">box1</div> <div class="box">box2</div> <div class="box">box3</div> <div class="box">box4</div> <div class="box">box5</div> </div> <div id="modal01" class="modal js-modal"> <div class="modal__bg js-modal-close"></div> <div class="modal__content"> <p>1つ目モーダルウィンドウです。ここにモーダルウィンドウで表示したいコンテンツを入れます。モーダルウィンドウを閉じる場合は下の「閉じる」をクリックするか、背景の黒い部分をクリックしても閉じることができます。</p> <a class="js-modal-close" href="">閉じる</a> </div><!--modal__inner--> </div><!--modal--> <div id="modal02" class="modal js-modal"> <div class="modal__bg js-modal-close"></div> <div class="modal__content"> <p>2つ目モーダルウィンドウです。ここにモーダルウィンドウで表示したいコンテンツを入れます。モーダルウィンドウを閉じる場合は下の「閉じる」をクリックするか、背景の黒い部分をクリックしても閉じることができます。</p> <a class="js-modal-close" href="">閉じる</a> </div><!--modal__inner--> </div><!--modal--> </body> |
サンプル2にスクロールができるように「box」を追加しただけです。
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
*{ box-sizing: border-box; margin: 0; padding: 0; } .content{ margin: 0 auto; padding: 40px; } .box{ background: #eee; height: 200px; margin-bottom: 100px; } .modal{ display: none; height: 100vh; position: fixed; top: 0; width: 100%; } .modal__bg{ background: rgba(0,0,0,0.8); height: 100vh; position: absolute; width: 100%; } .modal__content{ background: #fff; left: 50%; padding: 40px; position: absolute; top: 50%; transform: translate(-50%,-50%); width: 60%; } |
同じく「box」のスタイルが増えただけです。
jQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$(function(){ var winScrollTop; $('.js-modal-open').each(function(){ $(this).on('click',function(){ //スクロール位置を取得 winScrollTop = $(window).scrollTop(); var target = $(this).data('target'); var modal = document.getElementById(target); $(modal).fadeIn(); return false; }); }); $('.js-modal-close').on('click',function(){ $('.js-modal').fadeOut(); $('body,html').stop().animate({scrollTop:winScrollTop}, 100); return false; }); }); |
モーダルウィンドウを開く時にスクロール位置の取得と、閉じた時のスクロール位置を戻す処理が追加になっています。
2行目
スクロール位置の値を入れる変数「winScrollTop」を宣言しています。
6行目
「$(window).scrollTop()」で画面のスクロール位置(数値)が取得できますので、「js-modal-open」がクリックされたら、「winScrollTop」にスクロール位置を代入します。
15行目
「js-modal-close」がクリックされたら、取得しておいたスクロール位置まで、アニメーションさせながら移動しています。これで開いた時と閉じた時が同じスクロール位置になりました。
動画をモーダルウィンドウで表示する
冒頭の方で紹介した動画をモーダルウィンドウで表示するサンプルのソースコードも記載しておきますので、色々遊んでみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<body> <header class="site-header"> <h1 class="site-logo"><img src="images/logo.png" alt="WEBDESIGNDAY"></h1> <nav class="gnav"> <ul class="gnav__menu"> <li class="gnav__menu__item"><a href="">About</a></li> <li class="gnav__menu__item"><a href="">Works</a></li> <li class="gnav__menu__item"><a href="">Recruit</a></li> <li class="gnav__menu__item"><a href="">News</a></li> <li class="gnav__menu__item"><a href="">Contact</a></li> </ul> </nav> </header> <div class="hero"> <video class="hero__video" src="images/video.mp4" loop muted autoplay></video> <a class="modal-open js-modal-open" href="" data-target="modal01">動画を見る</a><br> </div> <div class="content"> <div class="box">box1</div> <div class="box">box2</div> <div class="box">box3</div> <div class="box">box4</div> <div class="box">box5</div> </div> <div id="modal01" class="modal js-modal"> <div class="modal__bg js-modal-close"></div> <div class="modal__content"> <video class="hero__video" src="images/video.mp4" loop muted autoplay></video> <a class="js-modal-close" href="">閉じる</a> </div><!--modal__inner--> </div><!--modal--> </body> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
*{ box-sizing: border-box; margin: 0; padding: 0; } .site-header{ background: rgba(255,255,255,0.8); display: flex; padding:20px; position: fixed; justify-content: space-between; width: 100%; } .site-logo img{ height: 20px; width: auto; } .gnav__menu{ display: flex; } .gnav__menu__item{ list-style: none; margin-left: 20px; } .gnav__menu__item a{ color: #333; text-decoration: none; } .hero{ position: relative; } .hero__video{ height: auto; width: 100%; } .content{ margin: 0 auto; padding: 40px; } .box{ background: #eee; height: 200px; margin-bottom: 100px; } .modal-open{ background: #fff; color: #222; left: 50%; padding: 10px 40px; position: absolute; top: 50%;transform: translate(-50%,-50%); } .modal{ display: none; height: 100vh; position: fixed; top: 0; width: 100%; } .modal__bg{ background: rgba(0,0,0,0.8); height: 100vh; position: absolute; width: 100%; } .modal__content{ background: #fff; left: 50%; padding: 40px; position: absolute; top: 50%; transform: translate(-50%,-50%); width: 60%; } |
jQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$(function(){ var winScrollTop; $('.js-modal-open').each(function(){ $(this).on('click',function(i){ //スクロール位置を取得 winScrollTop = $(window).scrollTop(); var target = $(this).data('target'); var modal = document.getElementById(target); $(modal).fadeIn(); return false; }); }); $('.js-modal-close').on('click',function(){ $('.js-modal').fadeOut(); $('body,html').stop().animate({scrollTop:winScrollTop}, 100); return false; }); }); |
モーダルウィンドウに限らずサイトにギミックを取り入れる際は、ユーザビリティも考慮して本当に必要なものを取り入れることで、ユーザーエクスペリエンスが向上するものを取り入れていきたいですね。