サムネイル画像をクリックすると大きな画像がポップアップして表示される「モーダルウィンドウ」の作り方を学習しました
機能の紹介
今回作成するモーダルウィンドウの機能を簡単に紹介します。
- クリックしたら、ポップアップ画像を表示
- ポップアップ画像の背景に半透明の黒い背景でウインドウ全体を覆う(オーバーレイという)
- ポップアップ画像表示中はスクロールさせない
- オーバーレイ部分をクリックすると、ポップアップを非表示にさせる
完成コード
完成イメージです↓
See the Pen モーダルウィンドウ by ユイト (@mikiprogram) on CodePen.
HTMLの作成
まず、HTMLを作成していきます。
JavaScriptが無効な環境であっても、ポップアップ用の画像が表示できるように、
img要素をa要素で囲み、a要素のhref属性にポップアップ用の画像パスを記述します。
また、JavaScirptで操作する要素のclass属性にはjs-の接頭辞をつけます。
<a class="m-modalLink js-modalWindow" href="https://drive.google.com/uc?export=view&id=15Dom_6c0greOYOl_ADjkXf0wgwpiHfNP">
<img class="m-modalImage" src="https://drive.google.com/uc?export=view&id=18q6XsxqI_GPdlOyr52D1t5WQwz5pJvoY" alt="ぶどう">
</a>
表示用イベントの作成
クリックイベントの作成とa要素のページ遷移機能を無効化
a要素のclass属性.js-modalWindow
にクリックイベントを作成していきます。
また、通常a要素はクリックするとページ遷移するため、クリックイベントの最後に
return:false;
を追加して、ページ遷移機能を無効化します。
$(function () {
//クリックイベントを作成
$(".js-modalWindow").click(function() {
//a要素のページ遷移機能を無効化
return false;
});
})
オーバーレイの作成
a要素をクリックしたら、オーバーレイが表示されるようにしていきます。
まず、append()
を使ってbody要素の末尾に
class属性.overlay
の付いた空divを作成します。
$(function() {
$(".js-modalWindow").click(function() {
//body要素の末尾に空divを作成
$("body").append("<div class='overlay'></div>");
return false;
})
})
次に、CSSでoverlay
を装飾します。
.overlay {
display:none;
position: fixed;
inset:0 auto 0 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgba(0, 0, 0, .5);
}
オーバーレイをフェードインして表示
オーバーレイをフェードインで表示させるために、fadeIn()
を使います。
単位はmsなので0.3秒かけて表示させる場合、fadeIn(300)
のように記述します。
$(function() {
$(".js-modalWindow").click(function() {
$("body").append("<div class='overlay'></div>");
//オーバーレイをフェードインで表示
$(".overlay").fadeIn(300);
return false;
});
})
fadeIn()
は、非表示の要素をフェードインさせるメソッドのため、
最初に、CSSでdisplay:none
を指定して、オーバーレイを非表示にする必要があります。
フェードイン効かない時の対処法について→【jQuery】fadeIn()が効かない場合の対処法を4つ解説!
ポップアップ用画像の作成
ポップアップ用の画像を以下の手順で作成していきます。
クリックされたa要素のhref属性を取得
まずattr()
を使ってクリックされたa要素の href属性を取得し、変数にまとめます。
$(function() {
$(".js-modalWindow").click(function() {
$("body").append("<div class='overlay'></div>");
$(".overlay").fadeIn(300);
//クリックされたa要素のhref属性を取得
var target = $(this).attr("href");
return false;
});
})
$(".js-modalWindow").attr("href");
と指定すると、ブラウザをリロードしない限り、
初めにクリックされたa要素のhref属性を取得したままとなります。
違う画像のa要素をクリックしてもhref属性を取得できないので、
表示させたい画像とは違う画像が表示されてしまいます。
こういう場合に、$(this).attr("href");
と指定すると
クリックされたa要素のhref属性を取得できるため、
表示させたい画像を表示できます。
ポップアップ用のimg要素を変数にまとめる
次に、ポップアップ用のimg要素を変数にまとめます。
先ほど取得したhref属性をimg要素のsrc属性に指定します。
$(function() {
$(".js-modalWindow").click(function() {
$("body").append("<div class='overlay'></div>");
$(".overlay").fadeIn(300);
var target = $(this).attr("href");
//ポップアップ用のimg要素を変数にまとめる
var largeImage = "<img class='modalContent' src='" + target + "' >";
return false;
});
})
またimg要素にclass属性を追加して、CSSにスタイルを指定します。
ポップアップ用の画像が画面全体に対して、上下左右中央配置にします。
また画像が大きくなりすぎないように、幅と高さに最大値を設定します。
.modalContent {
position: absolute;
inset:0;
margin: auto;
max-width: 80%;
max-height: 80%;
}
ポップアップ用のimg要素を空divの中に追加
ポップアップ用のimg要素を空divの中にappend()
を使って追加します。
変数をappend()
に使用するときは、引用符を付けずにそのまま変数名を指定します。
引用符を指定すると、 変数名が文字列として認識されてしまうためです。
$(function() {
$(".js-modalWindow").click(function() {
$("body").append("<div class='overlay'></div>");
$(".overlay").fadeIn(300);
var target = $(this).attr("href");
var largeImage = "<img class='modalContent' src='" + target + "' >";
//ポップアップ用のimg要素を空divの中に追加
$(".overlay").append(largeImage);
return false;
});
})
ポップアップ画像が表示中は画面スクロールを無効化
ポップアップ画像が表示されている間は、画面スクロールを無効化するため、
body要素にclass属性.is-active
を追加し、
CSSで.is-active
にoverflow:hidden;
を指定します。
$(function() {
$(".js-modalWindow").click(function() {
$("body").append("<div class='overlay'></div>");
$(".overlay").fadeIn(300);
var target = $(this).attr("href");
var largeImage = "<img class='modalContent' src='" + target + "' >";
$(".overlay").append(largeImage);
//body要素にclass属性を追加
$("body").addClass("is-active");
return false;
});
})
.is-active {
overflow:hidden;
}
非表示イベントの作成
オーバーレイ部分をクリックすると、フェードアウトさせる
オーバーレイ部分をクリックするとフェードアウトさせるため、
新たにクリックイベントを作成します。
そして、fadeOut()
を使って0.3秒かけてフェードアウトさせます。
$(function () {
$(".js-modalWindow").click(function() {
$("body").append("<div class=overlay></div>");
$(".overlay").fadeIn(300);
var target = $(this).attr("href");
var largeImage = "<img class='modalContent' src='" + target + "'>";
$(".overlay").append(largeImage);
$("body").addClass("is-active");
return false;
});
//非表示用イベントの作成
$("body").on("click",".overlay",function() {
//オーバーレイをフェードアウトさせる
$(this).fadeOut(300);
});
});
これで完成!!
かと思いきや、一度目のクリックでは見た目上ちゃんとオーバーレイがフェードアウトして、元の状態に戻り問題ないのですが、複数回a要素をクリックすると、
複数回オーバレイ部分をクリックしないと元の状態に戻りません。
なぜかというと、fadeIn(),fadeOut()
は
display
プロパティを表示・非表示にしているだけなので、
空div自体はHTML上に残ってしまいます。
そのため要素自体を完全に削除する必要があります。
フェードアウトのみの動画がこちらです↓
コールバック関数を使って、フェードアウト後に空divを削除
フェードアウトだけでは空div自体を削除することはできませんでした。
そのため、要素を削除するremove()
を使っていきます。
$(function () {
$(".js-modalWindow").click(function() {
$("body").append("<div class=overlay></div>");
$(".overlay").fadeIn(300);
var target = $(this).attr("href");
var largeImage = "<img class='modalContent' src='" + target + "'>";
$(".overlay").append(largeImage);
$("body").addClass("is-active");
return false;
});
$("body").on("click",".overlay",function() {
$(this).fadeOut(300,function() {
//フェードアウトが終了した後に空div要素を削除
$(this).remove();
});
});
});
$(this).fadeOut(300).remove();
のようにメソッドチェーンを使って
remove()
を指定する方法や、
単純に$(this).remove();
を$(this).fadeOut(300);
の次の行に指定する方法では、
フェードアウトせずパッと空divが削除されます。
フェードアウトが終わった後に空divを削除するため、
コールバック関数を使います。
フェードアウトの比較動画がこちら↓
body要素に追加したclass属性を削除
最後にbody要素に追加したclass属性を削除して完成です。
$(function () {
$(".js-modalWindow").click(function() {
$("body").append("<div class=overlay></div>");
$(".overlay").fadeIn(300);
var target = $(this).attr("href");
var largeImage = "<img class='modalContent' src='" + target + "'>";
$(".overlay").append(largeImage);
$("body").addClass("is-active");
return false;
});
$("body").on("click",".overlay",function() {
$(this).fadeOut(300,function() {
$(this).remove();
//body要素に追加したclass属性を削除
$("body").removeClass("is-active");
});
});
});