概要
dialog要素でモーダルを表示しつつ、template要素で表示する内容を切り替えるモーダルウィンドを作成します。
サンプル
ソース
HTML
<div>
<button class="showDialog" data-id="template1">template1</button>
</div>
<div>
<button class="showDialog" data-id="template2">template2</button>
</div>
<div>
<button class="showDialog" data-id="template3">template3</button>
</div>
<dialog id="favDialog">
<form>
<div class="content-wrap">
<button value="cancel" formmethod="dialog" class="btn-close"></button>
<div class="content-main"></div>
<div class="btns">
<button value="cancel" formmethod="dialog">Close</button>
</div>
</div>
</form>
</dialog>
<template id="template1">
<div>
template1
</div>
</template>
<template id="template2">
<div>
template2
</div>
</template>
<template id="template3">
<div>
template3
</div>
</template>
dialog
の中をform
で囲っています。button
にformmethod="dialog"
を指定することによってモーダルウィンドウを閉じることができます。
template
はIDを振って表示させたいコンテンツ内容をコーディングしています。
表示元のボタンに設定したdata-id="template1"
とtemplate id="template1"
をtemplate1(ユニークな値)
合わせることによってモーダルウィンドウの内容を出し分けます。
CSS
#favDialog{
width: 100%;
max-width: 100%;
max-height: 100%;
border: none;
background-color: transparent;
position: fixed;
z-index:1000;
left: 0;
top: 0;
padding: 0;
margin: auto;
user-select: text;
visibility: visible;
inset-block-start: 0;
inset-block-end: 0;
}
#favDialog::backdrop{
display: none;
}
#favDialog::before{
content: "";
display: block;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #000000aa;
}
#favDialog,
#favDialog::before{
animation: fadeout 500ms ease forwards;
}
#favDialog[open],
#favDialog[open]::before{
animation: fadein 500ms ease forwards;
}
#favDialog form{
display: block;
padding: 40px 0 30px 0;
position: relative;
}
#favDialog .btns{
text-align: center;
}
#favDialog .btn-close{
position: absolute;
top: -35px;
right: 0;
width: 30px;
height: 30px;
border: none;
background-color: transparent;
padding: 0;
}
#favDialog .btn-close:before{
content: "";
display: block;
width: 30px;
height: 2px;
background-color: #ffffff;
transform: rotate(-45deg);
transform-origin: 50% 50%;
}
#favDialog .btn-close:after{
content: "";
display: block;
width: 30px;
height: 2px;
background-color: #ffffff;
transform: translate(0,-2px) rotate(45deg);
transform-origin: 50% 50%;
}
#favDialog .content-wrap{
background-color: #ffffff;
max-width: 500px;
width:100%;
margin: 0 auto;
padding: 2rem;
border-radius: 10px;
border: 1px solid #000000;
position: relative;
z-index: 2;
}
@keyframes fadein{
0%{
opacity: 0;
}
100%{
opacity: 1;
}
}
@keyframes fadeout{
0%{
opacity: 1;
display: block;
}
99%{
opacity: 0;
display: block;
}
100%{
opacity: 0;
display: none;
}
}
dialog
の挙動が自分が実装したい挙動と違っていたのでCSSで無理やり変更しています。
また、アニメーションがないため、keyframes
を設定しています。
JavaScript
(function(){
window.addEventListener('load',()=>{
const showButtons = document.querySelectorAll(".showDialog");
const favDialog = document.getElementById("favDialog");
// ボタンで <dialog> をモーダルに開く
showButtons.forEach((item)=>{
item.addEventListener("click", (e) => {
let id = e.target.getAttribute('data-id');
const content = document.querySelector(`#${id}`).content;
const clone = document.importNode(content, true);
let $wrap = document.querySelector('#favDialog .content-main');
for (const child of $wrap.children) {
$wrap.removeChild(child);
}
$wrap.appendChild(clone);
favDialog.showModal();
});
});
document.querySelector('#favDialog').addEventListener('click',(e)=>{
if(e.target === e.currentTarget || e.target.tagName.toLowerCase() === 'form'){
favDialog.close();
}
},false);
},false);
})();
let id = e.target.getAttribute('data-id');
const content = document.querySelector(`#${id}`).content;
const clone = document.importNode(content, true);
クリックしたボタンのdata-id
を取得して、template要素
を取得して要素をコピーしています。
let $wrap = document.querySelector('#favDialog .content-main');
for (const child of $wrap.children) {
$wrap.removeChild(child);
}
dialog要素に挿入する前にdialog内の要素を削除しておきます。
$wrap.appendChild(clone);
クローンした要素を挿入
favDialog.showModal();
モーダルを表示
document.querySelector('#favDialog').addEventListener('click',(e)=>{
if(e.target === e.currentTarget || e.target.tagName.toLowerCase() === 'form'){
favDialog.close();
}
},false);
モーダル背景をクリックで閉じるようにしています。
Github
https://github.com/hiron712/dialog_template
ブラウザ対応
IEがほぼなくなった今、一部関数が使えない場合があるのでそこを気をつければ、使用しても良いのではないでしょうか?
まとめ
dialog要素の挙動は決まっているので、自分自身が実装したい挙動と違う場合は難しいかもしれませんが、ブラウザがモーダルウィンドを制御してくれているのでその分のJavaScriptを書かなくて済む、モーダルにフォームが表示できて値を渡すことができる、ESCキーでモーダルを閉じることができるなど、メリットもあるので使用しても良いと思います、
コメントを投稿する