dialog要素と@starting-styleでふわっと表示させる方法

## はじめに

こんな感じの、ふわっと表示・ふわっと閉じるアニメーションを実現する方法をご紹介します。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/10b694d9-b44a-4bfc-96b5-225442a8f2d5.gif">

## 通常のダイアログ表示

まずはスタイルを指定せず、ダイアログの表示・非表示を作成します。

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button
    id="open-dialog-button"
    type="button"
  >
    ダイアログを開く
  </button>

  <dialog id="dialog">
    <p>ダイアログです</p>
    <button
      id="close-dialog-button"
      type="button"
    >
        ダイアログを閉じる
    </button>
  </dialog>

  <script>
    const openDialogButtonElement = document.getElementById("open-dialog-button");
    const closeDialogButtonElement = document.getElementById("close-dialog-button");
    const dialogElement = document.getElementById("dialog");

    openDialogButtonElement.addEventListener("click", () => {
      dialogElement.showModal();
    });

    closeDialogButtonElement.addEventListener("click", () => {
      dialogElement.close();
    });

  </script>
</body>
</html>
```

全くふわっとしていません。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/583a3b08-4743-439e-acd3-56d4cab4a62f.gif">

## ふわっと表示を実現

`@starting-style`を使って、ふわっと表示させます。
`@starting-style`は、要素が追加された時や`display`が`none`から`block`などに変更された時に適用されます。

```html
  <style>
    dialog {
      transition: opacity 1s, translate 1s;

      &[open] {
        opacity: 1;
        translate: 0 0;

        @starting-style {
          opacity: 0;
          translate: 0 20px;
        }
      }
    }
  </style>
```

今回の場合は、ダイアログを開く前は`display`が`none`で、開いた後は`display`が`block`に変更されるため、`@starting-style`が適用され、`transition`の指定により、ふわっと表示がされました。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/e3a88a45-0a1e-4748-9867-89d2935ca50e.gif">


:::note info
`@starting-style`を使用しなくても実現できるのでは？と思う方もいるかもしれませんが、`display`が`none`から`block`に切り替わる場合は`transition`が効きません。
:::

## ふわっと閉じるを実現

`transition-behavior`の`allow-discrete`を使って、ふわっと閉じるようにします。
`allow-discrete`は離散プロパティに対してトランジションを適用させるものです。
`overlay`と`display`は離散プロパティで、トランジションの効果を受けないため、`allow-discrete`を指定して、トランジションが適用されるようにしてます。

```html
  <style>
    dialog {
      opacity: 0;
      translate: 0 20px;
      transition:
        opacity 1s,
        translate 1s,
        overlay 1s allow-discrete,
        display 1s allow-discrete;

      &[open] {
        opacity: 1;
        translate: 0 0;

        @starting-style {
          opacity: 0;
          translate: 0 20px;
        }
      }
    }
  </style>
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/987f84a2-3ae7-4bda-a602-bf5d4df3078a.gif">

:::note warn
firefoxの137.0.2のバージョン以前では、閉じるアニメーションは対応していません。
:::

## backdropもアニメーション

backdrop（背景の黒透明）のアニメーションがまだできていません。
こちらはダイアログで指定した方法と同じように、`@starting-style`を使用することで、ふわっと表示されるようになります。

```html
  <style>
    dialog {
      （省略）

      &::backdrop {
        opacity: 0;
        transition: opacity 1s;
      }

      &[open]::backdrop {
        opacity: 1;

        @starting-style {
          opacity: 0;
        }
      }
    }
  </style>
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/07ca828b-16e1-4ae1-b1d3-8b3b5f6387dd.gif">

<details><summary>すべてのコード</summary>

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <style>
    dialog {
      opacity: 0;
      translate: 0 20px;
      transition:
        opacity 1s,
        translate 1s,
        overlay 1s allow-discrete,
        display 1s allow-discrete;

      &[open] {
        opacity: 1;
        translate: 0 0;

        @starting-style {
          opacity: 0;
          translate: 0 20px;
        }
      }

      &::backdrop {
        opacity: 0;
        transition: opacity 1s;
      }

      &[open]::backdrop {
        opacity: 1;

        @starting-style {
          opacity: 0;
        }
      }
    }
  </style>

  <button
    id="open-dialog-button"
    type="button"
  >
    ダイアログを開く
  </button>

  <dialog id="dialog">
    <p>ダイアログです</p>
    <button
      id="close-dialog-button"
      type="button"
    >
        ダイアログを閉じる
    </button>
  </dialog>

  <script>
    const openDialogButtonElement = document.getElementById("open-dialog-button");
    const closeDialogButtonElement = document.getElementById("close-dialog-button");
    const dialogElement = document.getElementById("dialog");

    openDialogButtonElement.addEventListener("click", () => {
      dialogElement.showModal();
    });

    closeDialogButtonElement.addEventListener("click", () => {
      dialogElement.close();
    });

  </script>
</body>
</html>
```
</details>

## まとめ

ダイアログのふわっと表示・ふわっと閉じる方法をご紹介しました。
モダンCSSを使うことで、JavaScript無しでもアニメーションが作れるので、皆さんも是非。

## 参考記事

https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/dialog

https://developer.mozilla.org/ja/docs/Web/CSS/@starting-style

https://developer.mozilla.org/ja/docs/Web/CSS/transition-behavior

https://cly7796.net/blog/css/try-using-starting-style/

## 最後に

### GoQSystemでは一緒に働いてくれる仲間を募集中です！

ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=22c04508981791f77a73