【JavaScript】クリックしたらモーダルウィンドウで詳細情報を表示する
2024年06月06日
WEBサイト制作
- #HTML
- #css
- #JavaScript
- #tips
こんにちは!
上毛印刷WEB制作担当のソーヤです。
今回は使用頻度が高い「モーダルウィンドウ」の実装方法についてご紹介します!
ちなみによく「ポップアップ」と勘違いしている方を見かけますが、
「ポップアップ」は、現在開いているウィンドウとは違う、別ウィンドウで表示されるコンテンツを指します。
「モーダルウィンドウ」は、現在開いているウィンドウにHTML・CSS・JavaScriptで表示されるコンテンツを指します。
全然違うものなので注意してくださいね。
今回の実装例は少し特殊なので、デモページを作成しました。
アクセスしてみてください。
デモページはこちら(別タブで開きます)
HTML例
<div class="modalList-item js-item">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/IMG_1669.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/IMG_1669.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> ネコかわいいですね。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
CSS例
.modalList-item {
width: 300px;
margin: 0 0 30px 0;
padding: 0 8px;
}
.modalList-item .modal-contents {
max-width: 700px;
}
.modalList-item a {
display: block;
position: relative;
width: 100%;
height: 100%;
color: #333;
background-color: #fff;
box-shadow: 9px 8px 10px rgba(0, 0, 0, 0.2), 0 0 5px 0 #ffffff, -4px 0 5px 0 #ffffff, -4px -6px 15px #ffffff;
transition: .4s ease;
}
.modalList-item a:hover {
transform: scale(1.01);
box-shadow: 15px 14px 17px rgba(0, 0, 0, 0.2), 0 0 8px 0 #ffffff, -7px 0 8px 0 #ffffff, -7px -10px 26px #ffffff;
opacity: 0.7;
}
.modalList-item a:hover::after {
transform: translateX(10px);
}
.modalList-item h3 {
padding: 20px 10px 40px;
font-size: 22px;
font-weight: bold;
line-height: 1.2;
}
.modalList-item h3 span {
font-size: 14px;
}
.modalButton-img {
position: relative;
}
.modalButton-img img {
width: 100%;
max-width: 100%;
margin: 0 0 20px;
vertical-align: top;
}
.modalInner-img {
position: relative;
margin: 0 0 20px;
}
.modalInner-img img {
width: 100%;
max-width: 100%;
margin: 0 0 20px;
vertical-align: top;
}
.modalInner-img + h3 {
display: flex;
-webkit-box-align: end;
-webkit-align-items: flex-end;
-ms-flex-align: end;
align-items: flex-end;
padding: 0 10px 20px 0;
}
.modalList-item .modal-contents {
max-width: 700px;
}
.modal {
display: none;
z-index: 9999;
position: fixed;
top: -10px;
right: 0;
bottom: -10px;
left: 0;
overflow: hidden;
overflow-y: auto;
backface-visibility: hidden;
background-color: rgba(0, 0, 0, 0.45);
}
.modal-container {
display: table;
width: 100%;
height: 100%;
padding: 10px 0;
}
.modal-inner {
display: table-cell;
padding: 2.7em 2em;
vertical-align: middle;
}
.modal-contents {
position: relative;
max-width: 1300px;
margin: 0 auto;
padding: 30px;
background-color: #fff;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
text-justify: inter-ideograph;
}
.modal-button-wrap {
position: absolute;
top: 20px;
right: 20px;
}
.modal-button {
appearance: none;
display: inline-block;
position: relative;
width: 24px;
height: 24px;
border: none;
outline: none;
background: transparent;
line-height: 1;
text-indent: -9999px;
vertical-align: middle;
cursor: pointer;
}
.modal-button::before {
position: absolute;
top: -25px;
left: 57px;
width: 30px;
height: 30px;
border: 5px solid #fff;
border-radius: 50%;
background-color: #fff;
background-image: url(/cp/wp/wp-content/uploads/2024/06/modal_close.png);
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
content: '';
cursor: pointer;
}
JavaScript例
document.addEventListener('DOMContentLoaded', function() {
var windowEl = window,
html = document.documentElement,
body = document.body,
scrollbarWidth = window.innerWidth - document.body.scrollWidth,
touchStartY;
windowEl.addEventListener('touchstart', function(event) {
touchStartY = event.changedTouches[0].screenY;
});
document.querySelectorAll('.js-modal').forEach(function(modalTrigger) {
modalTrigger.addEventListener('click', function() {
var overlay = modalTrigger.nextElementSibling;
windowEl.addEventListener('touchmove', touchMoveHandler, { passive: false });
html.style.overflow = 'hidden';
body.style.overflow = 'hidden';
if (scrollbarWidth) {
html.style.paddingRight = scrollbarWidth + 'px';
}
overlay.style.display = 'block';
overlay.style.opacity = 1;
overlay.style.transition = 'opacity 0.3s';
var touchMoveHandler = function(event) {
var currentY = event.changedTouches[0].screenY,
height = overlay.offsetHeight,
isTop = touchStartY <= currentY && overlay.scrollTop === 0,
isBottom = touchStartY >= currentY && overlay.scrollHeight - overlay.scrollTop === height;
if (isTop || isBottom) {
event.preventDefault();
}
};
var closeModal = function() {
body.style.removeProperty('overflow');
html.style.removeProperty('overflow');
html.style.removeProperty('padding-right');
windowEl.removeEventListener('touchmove', touchMoveHandler);
overlay.style.transition = 'opacity 0.3s';
overlay.style.opacity = 0;
setTimeout(function() {
overlay.scrollTop = 0;
overlay.style.display = 'none';
overlay.style.removeProperty('style');
html.style.removeProperty('style');
}, 300);
};
overlay.addEventListener('click', function(event) {
if (!event.target.closest('.modal-contents')) {
closeModal();
}
});
overlay.querySelector('.modal-button').addEventListener('click', function() {
closeModal();
});
});
});
});
まとめ
今回もjQueryではなく、Vanilla.jsで実装してみました。
コピペしてガンガン使ってください!
この記事に対するご意見・ご感想・ご質問等ありましたら、
ぜひ下記フォームにてお送りください。