たとえば「モーダルの背景をクリックしたとき」のように、指定した領域の外側をクリックしたときに要素を閉じる方法について解説します。
領域外をクリックしたときに「閉じる」イベントを発動するjQueryの書き方
jQueryで領域外をクリックしたときにイベントを発生させるには、下記のコードを使います。
$(document).click(function(e) {
if(!$(e.target).closest(指定した要素).length) {
//イベント内容
}
});
解説
まずは下記コードでページ全体のクリックイベントを検出しています。
$(document).click(function(e) {
});
そして次の部分では、クリックされた要素が指定した要素自身もしくはその子孫要素以外かどうかを判定しています。
つまり、指定した要素の領域外をクリックした場合に限りイベントが発生する、ということですね。
たとえば「ある要素を閉じる」という場合は、ここに何らかのイベントを書けばOKです。
if(!$(e.target).closest(指定した要素).length) {
//要素を閉じるためのイベントを書く
}
実例を見た方がわかりやすいと思うので、モーダルを例に解説します。
「領域外をクリックしたらモーダルが閉じる」をjQueryで作ってみよう
まず今回サンプルとなるモーダルを見てみましょう。
「モーダルを開く」をクリックするとモーダルが開き、黒の背景をクリックするとモーダルが閉じます。
今回の場合、内側にある画像をクリックしてもモーダルは閉じません。
See the Pen Untitled by たけち (@kwxteqls-the-scripter) on CodePen.
では、コードを解説します。
解説
HTML、CSS、jQueryの順に解説します。
HTML
<div class="content">
<button class="btn">モーダルを開く</button>
</div>
<div class="modal">
<div class="image">
<img src="https://drive.google.com/uc?export=view&id=14iiKkR1K7wA_ww22HzBzPTylwhxdbl7M" alt="">
</div>
</div>
contentというブロックと、それとは別にmodalというブロックを作りました。
contentにはボタンを、modalには画像を配置しています。
もちろんこのままだとcontent→modalの順に配置されるだけなので、CSSで調整します。
CSS
.content {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.8);
opacity: 0;
visibility: hidden;
transition: all 0.5s;
}
.modal.open {
opacity: 1;
visibility: visible;
}
.image {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn {
border: none;
background-color: lightblue;
padding: 10px;
border-radius: 8px;
cursor: pointer;
}
modalは画面全体に表示させたいのでposition: fixed
にして、幅と高さをそれぞれ100%、100vhにしています。
画像はmodalの中央に配置しました。
背景は透過0.8の黒です。
modalはいったん非表示にしたいので、opacity: 0
とvisibility: hidden
にします。
すぐ下に「.modal.open」というクラス名でopacity: 1
とvisibility: visible
を指定しています。
これはモーダルが開いたときのCSSですね。
jQueryで.openクラスを付け外ししてmodalの表示・非表示を切り替えるという仕組みです。
他は見た目のスタイリングになります。
jQuery
今回のポイントであるjQueryは次の通りです。
//画像の外側をクリックしたらモーダルが閉じる
$(document).click(function(e) {
if(!$(e.target).closest('.image').length) {
$('.modal').removeClass('open');
}
});
//ボタンをクリックするとモーダルが開く
$(".btn").click(function(e) {
e.stopPropagation();
$('.modal').addClass('open');
});
$(document).click(function(e) { });
で画面全体のクリックイベントを検出しています。
if(!$(e.target).closest('.image').length) { }
では「imageクラスを持つ要素もしくはその子孫要素以外」という条件分岐を行っています。
つまり、画像の外側をクリックしたときだけイベントが発生することになります。
イベントとは$('.modal').removeClass('open');
の部分ですね。
modalからopenクラスを外す処理です。
これで画像の領域外をクリックしたときにモーダルを閉じる処理が完成しました。
ちなみに、ボタンのクリックイベントにe.stopPropagation();
という見慣れない書き方がありますが、これは「クリックイベントの伝播を防ぐためのもの」です。
JavaScriptには「バブリング」という現象があり、あるイベントが発生するとそのイベントは親要素・祖先要素にまで波及するという特徴があります。
今回の場合、ボタンをクリックすると、クリックイベントは$(document).click(function(e) { });
にまで伝播します。
つまりボタンのクリックイベントでモーダルを開いても、画面全体のクリックイベントでモーダルが閉じてしまう「バグ」が発生するということですね。
これを防ぐためにe.stopPropagation();
を書いています。
余談ですが、頭の片隅に入れておくといいでしょう。