などの疑問や悩みを解決してまいります。
何かしらのコンテンツを拡大して見せたいときに重宝するモーダルウィンドウですが、実装が難しいと思っていませんか。
しかし、コードを紐解いて確認してみると仕組みはシンプルです。
この記事では初心者や苦手意識がある方でも簡単に実装できる方法をわかりやすく解説します。
モーダルウィンドウの完成例
See the Pen モーダルウィンドウ【外クリックなし】 by koutarou mori (@koutarou-mori) on CodePen.
ボタンをクリックで表示、×印クリックで閉じるといったシンプルなモーダルウィンドウです。
モーダルウィンドウの仕組みはいたって単純で、ボタンをクリックしたら非表示にしているモーダルウィンドウを表示させるといったものになります。
それではソースコードをそれぞれ見ていきましょう。
HTML解説
HTMLは以下になります。
<body>
<div class="modal">
<div class="modalBtn">
<p>クリックするとモーダルが表示</p>
</div><!-- /.modalBtn -->
<div class="modalBg">
<div class="modalArea">
<div class="modalClose"></div><!-- /.modalClose -->
<p>
モーダル内のコンテンツがここに表示されます。
モーダル内のコンテンツがここに表示されます。
モーダル内のコンテンツがここに表示されます。
モーダル内のコンテンツがここに表示されます。
モーダル内のコンテンツがここに表示されます。
</p>
</div><!-- /.modalArea -->
</div><!-- /.modalBg -->
</div><!-- /.modal -->
</body>
モーダルウィンドウを表示させるために必要な機能は、表示させるためのボタン要素とモーダルウィンドウの要素、そしてウィンドウを閉じるためのボタン要素です。
上記コードではクリック対象となるのがmodalBtnクラスで、modalBtnクラスがクリックされるとモーダルウィンドウの親要素であるmodalBgクラスが非表示から表示に切り替わります。
modalCloseクラスは閉じるための要素で、CSSで×印ボタンを作成しています。
モーダルウィンドウのコンテンツはmodalAreaクラス内に入れます。
ポイント
〇 モーダルウィンドウを表示させるためのボタンを用意する
〇 モーダルウィンドウを表す要素を作成する
〇 モーダルウィンドウを閉じるボタンを用意する
CSS解説
/* リセットCSS */
body,div,p {
margin: 0;
}
.modal {
position: relative;
padding: 50px 0;
}
/* モーダルボタン */
.modalBtn {
width: 300px;
margin: 0 auto;
height: 50px;
line-height: 50px;
background-color: #db2e73;
border-radius: 50px;
cursor: pointer;
}
.modalBtn p {
font-size: 18px;
font-weight: bold;
text-align: center;
color: #fff;
}
/* モーダル背景 */
.modalBg {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, .8);
padding: 40px 0;
}
/* モーダル内コンテンツ */
.modalArea {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
background-color: #fff;
border-radius: 5px;
padding: 20px;
width: 80%;
}
.modalContent p {
font-size: 16px;
color: #222;
line-height: 1.5;
letter-spacing: .06em;
}
/* 閉じるボタン */
.modalClose {
position: relative;
background-color: #222;
border-radius: 50px;
width: 40px;
height: 40px;
margin: 0 0 40px auto;
cursor: pointer;
}
.modalClose::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%) rotate(45deg);
background-color: #fff;
border-radius: 50px;
width: 2px;
height: 20px;
}
.modalClose::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%) rotate(-45deg);
background-color: #fff;
border-radius: 50px;
width: 2px;
height: 20px;
}
一般的にモーダルウィンドウは画面の表示領域一杯に表示されます。
なのでモーダルウィンドウの背景となるmodalBgクラスにwidth: 100%;とheight: 100vw;を指定します。
今回は閉じるボタンを×印として作成していますが、疑似要素を使用して作成します。
×印を作るためにはtransformプロパティでrotateを指定します。
〇の中心に位置させたいので、transformプロパティに追加でtranslate: (-50%,-50%);を指定して上下左右中央に配置します。
またクリックができることをユーザー伝えるためcursorプロパティを指定して視覚効果を高めていきましょう。
ポイント
〇 モーダルウィンドウの背景には縦横幅を一杯にするCSSを指定する
〇 ×印はtransformプロパティのtranslateで上下左右中央配置、rotateで線を斜めにして作成する
JS解説
肝心のJSですが、やっていることはいたってシンプルで、「ボタンがクリックされたら、モーダルを表示する」と「閉じるボタンがクリックされたらモーダルを閉じる」というコードを記述します。
$(function () {
// ボタンをクリックしたらモーダル表示
$(".modalBtn").on("click", function () {
$(".modalBg").fadeIn();
});
// ×ボタンクリックでモーダル閉じる
$(".modalClose").on("click", function () {
$(".modalBg").fadeOut();
});
});
上記ではmodalBtnクラス(ボタン)がクリックされたら、modalBgクラス(モーダル)をフェードイン(表示)させるという動きと、modalCloseクラス(閉じるボタン)をクリックするとmodalBgクラス(モーダル)をフェードアウト(非表示)させるという動きを実装しています。
fadeIn()とfadeOut()を使用することで、モーダルの表示非表示の動きが滑らかになるのでおすすめです。
シンプルかつ短文なので、初心者の方でも理解しやすいコードかと思います。
ユーザビリティを意識したモーダルウィンドウ
ユーザビリティを意識したモーダルウィンドウです。
上の完成例との違いは、×印以外の黒背景部分をクリックしてもモーダルウィンドウを閉じることができます。
See the Pen モーダルウィンドウ【外クリックあり】 by koutarou mori (@koutarou-mori) on CodePen.
違いはJSのコードにあるのでコードを見ていきましょう。
$(function () {
// ボタンをクリックしたらモーダル表示
$(".modalBtn").on("click", function () {
$(".modalBg").fadeIn();
return false;
});
// ×ボタンクリックでモーダル閉じる
$(".modalClose").on("click", function () {
$(".modalBg").fadeOut();
});
// モーダルコンテンツ以外をクリックでモーダル閉じる
$(document).on("click", function (e) {
if (!$(e.target).closest(".modalArea").length) {
$(".modalBg").fadeOut();
}
});
});
追加したのは、return false;の部分と、モーダルコンテンツ以外をクリックでモーダルを閉じる指定です。
それぞれの意味を解説していきます。
モーダルコンテンツ以外をクリックでモーダル閉じる
追加されたコードを見てみましょう。
// モーダルコンテンツ以外をクリックでモーダル閉じる
$(document).on("click", function (e) {
if (!$(e.target).closest(".modalArea").length) {
$(".modalBg").fadeOut();
}
});
このコードは、要素をクリックした場合その要素の一番近い親要素はmodalAreaクラスを持っていない場合はmodalBgクラスをフェードアウトするという内容です。
「e」というのは要素を表し、e.targetはその要素を表します。
closest()は対象要素に一番近い親要素もしくは自分自身を取得します。
length()はその個数を表します。
つまり$(e.target).closest(".modalArea").lengthは、クリックされた要素の一番近い親要素はmodalAreaクラスであり、それは存在するかということになります。
それに加え「!」が付いていますので否定文となります。
よってif (!$(e.target).closest(".modalArea").length)の意味としては、クリックされた要素の一番近い親要素(もしくは自分自身)はmodalAreaクラスが存在しない場合…という条件式になります。
なのでmodalAreaクラスを基準に内側の要素をクリックしても、直近の親要素として、かつ自身がmodalAreaクラスがある限り条件には当てはまらないためモーダルは閉じません。
逆にmodalAreaクラスより外側の要素をクリックすると、親要素かつ自身にmodalAreaクラスはないため条件に当てはまりモーダルが非表示となります。
return false; の役割とは
実はこのコードがないと完成しません。バグが発生してしまいます。
このコードがないとどうなるのかを確認してみましょう。
See the Pen モーダルウィンドウ【return false;なし】 by koutarou mori (@koutarou-mori) on CodePen.
このようにボタンをクリックしても、すぐにモーダルが閉じてしまいます。
これはJavaScriptのイベント伝播の仕組みが原因となっています。
どういうことかといいますと、ある要素で発火したイベントはその全ての親要素に伝播していくということです。
上記のコードだと、まずmodalBtnクラスがクリックされることでイベントが発生します。
イベント発生と同時に親要素のmodalクラスにも伝番して、
// モーダルコンテンツ以外をクリックでモーダル閉じる
$(document).on("click", function (e) {
if (!$(e.target).closest(".modalArea").length) {
$(".modalBg").fadeOut();
}
});
このイベントも発火してしまって、モーダルが開いた瞬間に閉じてしまうといった現象が発生してしまいます。
この現象を防ぐのがreturn false;です。
return false;を使用することで親要素へのイベント伝播を止めることができるのです。
ポイント
〇 引数の「e」とはオブジェクトを受け取るための引数
〇 closest()は対象要素に一番近い親要素もしくは自分自身を取得
〇 length()はその個数を表す
〇 ある要素で発火したイベントはその全ての親要素に伝播する(バブリング)
〇 イベントの伝番を防ぐためのコードはreturn false;