Oteto Blogのロゴ

<dialog>なモーダルで背景 (backdrop) をクリックした時に閉じる

<dialog>で実装するモーダルで背景 (オーバーレイ) をクリックしても閉じるようにしたい時。::backdrop擬似要素にはイベントを登録できないので少しだけ困った。

コンテナ要素を追加する方法

<button>open modal</button>
<dialog>
  <div class="modal-content">
    modal content
  </div>
</dialog>
const button = document.querySelector('button');
const modal = document.querySelector('dialog');
const modalContent = document.querySelector('.modal-content');

button.addEventListener('click', () => {
  modal.showModal();
});
modal.addEventListener('click', (e) => {
  if (e.target !== modalContent) modal.close();
});

<dialog>直下にコンテナ要素を追加し、<dialog>クリック時にMouseEvent.targetがそのコンテナ要素でなければ閉じる、という方法。

コンテナ要素のサイズを親要素いっぱいに広げる必要がある。

<dialog>の寸法から判定する方法

<button>open modal</button>
<dialog>
  modal content
</dialog>
const button = document.querySelector('button');
const modal = document.querySelector('dialog');

button.addEventListener('click', () => {
  modal.showModal();
});
modal.addEventListener('click', ({ clientX, clientY }) => {
  const { top, left, width, height } = modal.getBoundingClientRect();
  const inDialog =
    top <= clientY &&
    clientY <= top + height &&
    left <= clientX &&
    clientX <= left + width;

  if (!inDialog) modal.close();
});

Element.getBoundingClientRect()<dialog>の寸法を取得し、MouseEvent.clientXMouseEvent.clientY がその中に収まっているか否かで背景をクリックしたかを判定する方法。

コンテナ要素を追加する必要が無いので個人的にはこっちが好み。