jQueryでモーダルウィンドウを作成

サムネイル画像をクリックすると、大きな画像がポップアップして表示される

モーダルウィンドウの作り方をshibajukuで学習しました。

目次

機能の紹介

今回作成するモーダルウィンドウの機能を簡単に紹介します。

  • クリックしたら、ポップアップ画像を表示
  • ポップアップ画像の背景に半透明の黒い背景でウインドウ全体を覆う(オーバーレイという)
  • ポップアップ画像表示中はスクロールさせない
  • オーバーレイ部分をクリックすると、ポップアップを非表示にさせる

では、早速作っていきます!

完成コード

See the Pen モーダルウィンドウ by ユイト (@mikiprogram) on CodePen.

コードと完成イメージは上記のような感じです。

モーダルウィンドウに関係のないコードは、

レイアウトや装飾目的のため無視してもらって大丈夫です。

では、以下より詳しく見ていきます!

HTMLの作成

まず、HTMLを作成していきます。

JavaSciptが無効な環境であっても、ポップアップ用の画像が表示できるように、

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>

多くのモーダルウィンドウの解説記事では、

オーバーレイ用の空div要素をHTMLでマークアップされるケースが多かったです。

しかし、レイアウト目的や装飾目的のために空div要素を使用しない方が良いらしいので、

JavaScriptを使って空div要素を追加したいと思います。

詳しくはこちら→中身のない空の div 要素や空の span 要素は HTML 仕様として妥当なのか?

表示用イベントの作成

クリックイベントの作成と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);
}

inset は、toprightbottomleft に対応する一括指定です。

詳しくはこちら→inset

オーバーレイをフェードインして表示

オーバーレイをフェードインで表示させるために、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%;
}

上記のスタイルを指定すると、なぜ上下左右中央配置になるのか雑に説明します。

まず、左右中央配置から説明すると、

right,left,widthの値がauto以外で、

margin-right,margin-leftの値がautoの場合、

margin-right,margin-left値が等しくなるように計算されるため、

左右中央配置になります。

上下中央配置も同じ原理で、

top,bottom,heightの値がauto以外で、

margin-top,margin-bottomの値がautoの場合、

margin-top,margin-bottom値が等しくなるように計算されるため、

上下中央配置になります。

詳しくはこちら→position: absolute; の指定で要素が上下左右中央配置になる理由

ポップアップ用の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-activeoverflow:hidden; を指定します。

addClass() を使うときは、追加したいclass名だけを指定します。

addClass(".is-active") のように、要素を選択する時と同じ感覚で指定すると、

.is-active先頭にドットが付いた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要素に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");
        });
    });
});

まとめ

今まで、コールバック関数やon() なんか聞いたことあるだけで、

「どこで使うねん」って思ってました。

今回の学習を通して、

何かの処理の後に別の処理を実行したいときは、コールバック関数を使ったり、

JavaScriptを操作して追加された要素に処理をしたいときは、on() を使うことが分かりました。

最後まで読んでいただきありがとうございました!!

shibajukuで学習中

僕の先生:@hilosiva

shibajukuのブログ:https://shibajuku.net/

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
目次