<button type="button" class="dialog__open-button" aria-expanded="false" aria-controls="modal">
モーダルダイアログを開く
</button>
<dialog id="modal" class="dialog">
<div class="dialog__inner">
<h2 class="dialog__heading">モーダルダイアログ</h2>
<button type="button" aria-controls="modal" aria-expanded="false" class="dialog__close-button">
モーダルダイアログを閉じる
</button>
</div>
</dialog>
.dialog {
padding:initial;
}
const dialog: HTMLDialogElement | null = document.querySelector('.dialog');
const openDialogButton: HTMLButtonElement | null = document.querySelector('.dialog__open-button');
const closeDialogButton: HTMLButtonElement | null = document.querySelector('.dialog__close-button');
const scrollLock = () => {
const scrollY = window.scrollY;
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;
document.body.style.left = '0';
document.body.style.width = '100%';
document.body.style.overflowY = 'scroll';
};
const scrollUnlock = () => {
const scrollY = document.body.style.top;
document.body.style.position = '';
document.body.style.top = '';
document.body.style.left = '';
document.body.style.width = '';
document.body.style.overflowY = '';
window.scrollTo(0, parseInt(scrollY || '0', 10) * -1);
};
const openDialog = () => {
dialog.showModal();
openDialogButton.setAttribute('aria-expanded', 'true');
closeDialogButton?.setAttribute('aria-expanded', 'true');
scrollLock();
};
const closeDialog = () => {
openDialogButton.setAttribute('aria-expanded', 'false');
closeDialogButton.setAttribute('aria-expanded', 'false');
if (dialog.open) {
dialog.close();
}
scrollUnlock();
};
openDialogButton.addEventListener('click', () => {
openDialog();
});
closeDialogButton.addEventListener('click', () => {
closeDialog();
});
dialog.addEventListener('click', (event) => {
// dialogのpadding部分ではなく、dialogの直接の子要素がクリックされた場合のみイベントリスナーを起動
if (!event.target.closest('.dialog__inner')) {
closeDialog();
}
});
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.