<div class="overlay"></div>
<div class="modal-window"></div>
<div class="image-viewer">
	<div class="main-image">
	</div>
	<ul class="nav">
	</ul>
</div>
img {
	height: auto;
	width: 100%;
}

.image-viewer {
	background: #dfdfdf;
	margin: 0 auto;
	width: 40%;
	@media screen and (max-width: 768px) {
		width: 100%;
	}
}

.main-image {
	background: #777;
	padding-bottom: 56.25%;
	margin-bottom: 10px;
	overflow: hidden;
	position: relative;
	> img {
		//opacity: 0;
		position: absolute;
		top: 0;
		left: 0;
		transition: 0.5s;
		//visibility: hidden;
		/*
    &.active {
      opacity: 1;
      visibility: visible;
      z-index: 100;
    }
    */
	}
}

.nav {
	font-size: 0;
	list-style: none;
	margin: 0;
	padding: 0;
	&-item {
		background: #ccc;
		display: inline-block;
		overflow: hidden;
		position: relative;
		padding-bottom: 14.0625%;
		width: 25%;
		/*
    @media screen and (max-width: 768px) {
      padding-bottom: 28.125%;
      width: 50%;
    }
    */
		> img {
			position: absolute;
			top: 0;
			left: 0;
		}
	}
}

.overlay {
	background: #000;
	height: 100%;
	opacity: 0;
	position: fixed;
	top: 0;
	left: 0;
	transition: 0.5s;
	-webkit-visibility: hidden;
	visibility: hidden;
	width: 100%;
	z-index: 1000;
	&.active {
		opacity: 0.6;
		visibility: visible;
	}
}

.modal-window {
	opacity: 0;
	position: fixed;
	top: 50%;
	left: 50%;
	transition: 0.5s;
	transform: translate(-50%, -50%);
	visibility: hidden;
	z-index: 2000;
	&.active {
		opacity: 1;
		visibility: visible;
	}
}
View Compiled
(() => {
	//画像に関するクラス
	class Asset {
		constructor() {
			this.urls = [
				"#",
				"#",
				"#",
				"#"
			];

			this._images = [];
		}

		get images() {
			return this._images;
		}

		//初期化するメソッド
		init() {
			this.createImage();
		}

		//画像を生成するメソッド
		createImage() {
			for (let i = 0; i < this.urls.length; i++) {
				const image = new Image();
				image.src = this.urls[i];
				this._images[i] = image;
			}
		}
	}

	//ナビゲーションに関するクラス
	class Nav {
		constructor() {
			this.elem = document.querySelector(".nav");
			this.navItems = null;
		}

		//ナビゲーションをクリックできる状態にするメソッド
		setupListener(mainImage) {
			this.navItems.forEach((navItem, index) =>
				navItem.addEventListener("click", e => {
					e.preventDefault();

					//クリックされたナビの画像
					const target = e.target;

					//複製
					const clone = target.cloneNode(true);

					//表示されている画像を削除
					mainImage.removeImage();

					//複製した画像を挿入
					mainImage.addImage(clone);
				})
			);
		}

		//ナビゲーションにサムネイルを挿入するメソッド
		insertThumbnail(images) {
			//.navに画像を挿入(画像が親要素を持たなければouterHTMLはエラーを発生する)
			images.forEach(image => this.elem.appendChild(image));

			//画像を.nav-itemで包む
			for (let i = 0; i < images.length; i++) {
				images[i].outerHTML = `<li class="nav-item">${images[i].outerHTML}</li>`;
			}

			this.navItems = document.querySelectorAll(".nav-item");
			//this.navItems.forEach(navItem => this.elem.appendChild(navItem));
		}
	}

	//メイン画像に関するクラス
	class MainImage {
		constructor() {
			this.elem = document.querySelector(".main-image");
		}

		//初期化するメソッド
		init(nav) {
			//先頭のサムネイル画像を複製
			const clone = nav.navItems[0].firstChild.cloneNode(true);

			//複製したサムネイル画像を表示
			this.addImage(clone);
		}

		//メイン画像をクリックできる状態にするメソッド
		setupListener(modalWindow, overlay) {
			this.elem.addEventListener("click", e => {
				e.preventDefault();
				const target = e.target;
				//console.log(target);

				//メイン画像を複製
				const clone = target.cloneNode(true);

				//それまで挿入されていたモーダルウィンドウの画像を削除
				modalWindow.removeImage();

				//複製したメイン画像をモーダルウィンドウに挿入
				modalWindow.addImage(clone);

				//オーバーレイを表示
				overlay.show();
			});
		}

		//.main-imageにメイン画像を挿入するメソッド
		addImage(image) {
			this.elem.appendChild(image);
			//image.classList.add("active");
		}

		//.main-imageからメイン画像を削除するメソッド
		removeImage() {
			this.elem.removeChild(this.elem.firstChild);
			//this.elem.firstChild.classList.remove("active");
		}
	}

	//モーダルウィンドウに関するクラス
	class ModalWindow {
		constructor() {
			this.elem = document.querySelector(".modal-window");
		}

		//モーダルウィンドウを表示するメソッド
		show() {
			this.elem.classList.add("active");
		}

		//モーダルウィンドウを非表示にするメソッド
		hide() {
			this.elem.classList.remove("active");
		}

		//.modal-windowに画像を挿入するメソッド
		addImage(image) {
			this.elem.appendChild(image);
			this.elem.classList.add("active");
		}

		//.modal-windowから画像を削除するメソッド
		removeImage() {
			//モーダルウィンドウ内に画像があれば(初回は無いためそのまま書くとエラーが発生する)
			if (this.elem.firstChild) {
				this.elem.removeChild(this.elem.firstChild);
				this.elem.classList.remove("active");
			}
		}
	}

	//オーバーレイに関するクラス
	class Overlay {
		constructor() {
			this.elem = document.querySelector(".overlay");
		}

		//オーバーレイをクリックできる状態にするメソッド
		setupListener(modalWindow) {
			this.elem.addEventListener("click", e => {
				e.preventDefault();

				//オーバーレイを非表示
				this.hide();

				//モーダルウィンドウを非表示
				modalWindow.hide();

				//モーダルウィンドウ内の画像を削除
				modalWindow.removeImage(modalWindow.elem.firstChild);
			});
		}

		//オーバーレイを表示するメソッド
		show() {
			this.elem.classList.add("active");
		}

		//オーバーレイを非表示にするメソッド
		hide() {
			this.elem.classList.remove("active");
		}
	}

	//インスタンス化
	const asset = new Asset();
	const nav = new Nav();
	const mainImage = new MainImage();
	const modalWindow = new ModalWindow();
	const overlay = new Overlay();

	//全体を初期化する関数
	function init() {
		asset.init();
		nav.insertThumbnail(asset.images);
		mainImage.init(nav);
		setupListeners();
	}

	//画像ビューアを操作できる状態にする関数
	function setupListeners() {
		nav.setupListener(mainImage);
		mainImage.setupListener(modalWindow, overlay);
		overlay.setupListener(modalWindow);
	}

	//起動
	init();
})();
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.