2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめてのアドベントカレンダーAdvent Calendar 2023

Day 15

dialog要素をEscキーでcloseした際にoverflow:hiddenを解除したい

Last updated at Posted at 2023-12-07

この記事で分かること

  • dialog要素でEscキーでcloseした際にoverflow:hiddenを解除する方法
  • dialog要素を使う利点、懸念点

背景

ダイアログをdialogタグで記述した際にescキーで閉じることができます(ブラウザーによって提供)。
しかし、overflow:hiddenを解除できなかったのでモーダルが消えてもスクロールができません。
そこでどうしたら良いか考えてみました。

補足)showModal() メソッドによって呼び出された<dialog>は、Escキーによって閉じることができます。

実装

モーダルを開く関数
openModal(){
    document.body.style.overflow = 'hidden';
    const modalElm = this.getModalElm();
    if (!(modalElm instanceof HTMLDialogElement)) return;
    modalElm.showModal();
}

以下の実装を当初は考えてました。
しかし、これだとキーを打つたびに毎回この処理が走るので良くないですね。

Escキーを押した際にバックドロップの固定を解除する関数
registerCanselModalEvent() {
        document.addEventListener('keydown', function(event) {
            if (event.key === 'Escape') {
                document.body.toggleAttribute('style');
            }
        });
};

このブログでcancelイベントというのを知りました。
dialog要素を使う今後のモーダル実装

HTMLElement: cancel event

The cancel event is fired by and elements. The event is fired when the user cancels the currently open dialog by closing it with the Esc key

mdnによると
dialogを開いている際にEscキーを押したらcancelイベントが発生すると記載があります。

こちらを採用したいと思います!

cancelイベントが起きた際にバックドロップの固定を解除する関数
registerCancelModalEvent() {
  const dialog = document.querySelector('dialog');
  if (dialog) {
    dialog.addEventListener("cancel", (event: Event) => {
      if (event.currentTarget === dialog) {
        document.body.toggleAttribute('style');
      }
    });
  }
}

inputタグをEscで閉じた際もcanselイベントが発生するので、Event.currentTargetを使っています。

例)ファイルピッカーダイアログ

補足

紹介した方もブログで書かれてましたが、以下の点でdialogタグは利点があります。

直感的な記述かつ実装が簡潔

今まで<div role="dialog">で記述して実装していましたがコード量が減ります。

modal.showModal();

  • モーダルを表示します。
  • CSS の ::backdrop 擬似要素を使用して、 要素が HTMLDialogElement.showModal() で表示されたときの背後のスタイルを設定することができます
    例)ダイアログの背後にある操作できないコンテンツを暗くする

modal.close();

  • モーダルを閉じます。
  • backdropが消えます。

デフォルトでEscキーで閉じることができる

cancelイベントを扱って実装ができる

懸念点

IEでは使えないです。

image.png>

image.png

デフォルトだとモーダルより下はスクロールしてしまいます。

今回のような実装はしないといけないですね。

  • modal.close()
  • Escキー押下時

参考

2
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?