CSSでフェードイン / アウトのフェードアウトで苦労した話

動的にDOMを追加削除するようなポップアップ（ここではアラートモーダル）のフェードイン/アウト、特にアウトを綺麗にアニメーションさせるのに試行錯誤した。

## 悩み点
フェードインしたポップアップにフェードアウト効果をつけていると、
ポップアップのDOMを設置した瞬間にフェードアウトアニメーションを実行してしまい、
画面がチラついてしまう。

## 対策
対策として、DOMを設置し、ポップアップを表示した際に、フェードアウト効果をつけることにした。
そうすることでDOMを設置した際にフェードアウト効果が発動しないようにした。

0. ポップアップを設置する
0. ポップアップに`.--show`クラス　を付与してポップアップを表示する
0. ポップアップを表示した際に`.--shown`というクラスも付与する。（このクラスにフェードアウト用のアニメーションが設定してある）
0. ポップアップから `.--show`　クラスを削除し、ポップアップを非表示にする。（フェードアウトアニメーションが実行される）

## 実際のコード

#### 追加時にチラついてしまうパターン

![oh.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73246/2b2808aa-c8db-3f11-12c7-a8f5208b2e34.gif)

```html:index.html　　追加時にチラついてしまうパターン
<!DOCTYPE html>
<html>
<head>
  <title>ポップアップをcssと少しだけjsでフェードイン / アウト</title>

  <style>

    .popup {
      position: absolute;
      top: 0;
      right: 0;
      visibility: hidden;
      opacity: 0;
      width: 200px;
      height: 200px;
      background: #DDD;
      padding: 1em;
      animation: fadeOutAnimation 0.2s;
    }
      
    .popup--show {
      visibility: visible;
      opacity: 1;
      animation: fadeInAnimation 0.2s;
    }
    
    @keyframes fadeInAnimation {
      0% {
        opacity: 0;
        visibility: visible;
      }
      100% {
        opacity: 1;
        visibility: visible;
      }
    }
    
    @keyframes fadeOutAnimation {
      0% {
        opacity: 1;
        visibility: visible;
      }
      100% {
        opacity: 0;
        visibility: hidden;
      }
    }
    
    </style>
    
    <script>
      function addPopup() {
        const newDiv = document.createElement('div');
        newDiv.classList.add('popup');
        newDiv.innerHTML = "ポップアップテスト";
        document.body.appendChild(newDiv);
      }
    </script>
</head>
<body>

<button onclick="addPopup()">ポップアップ追加</button>

</body>
</html>
```

#### 追加時にチラつかないパターン

![shown1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73246/d3065cc5-c717-cfd2-dbc4-a8462cc4a0e1.gif)

![shown2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73246/de7ee17d-b50d-952a-99c3-e8b0722daca1.gif)

```html:index.html　　追加時にチラつかないパターン
<!DOCTYPE html>
<html>
<head>
  <title>ポップアップをcssと少しだけjsでフェードイン / アウト</title>

  <style>

    .popup {
      position: absolute;
      top: 0;
      right: 0;
      visibility: hidden;
      opacity: 0;
      width: 200px;
      height: 200px;
      background: #DDD;
      padding: 1em;
    }

    /* --showよりも先に書いておく */
    .popup--shown {
      animation: fadeOutAnimation 0.2s;
    }
      
    .popup--show {
      visibility: visible;
      opacity: 1;
      animation: fadeInAnimation 0.2s;
    }
    
    @keyframes fadeInAnimation {
      0% {
        opacity: 0;
        visibility: visible;
      }
      100% {
        opacity: 1;
        visibility: visible;
      }
    }
    
    @keyframes fadeOutAnimation {
      0% {
        opacity: 1;
        visibility: visible;
      }
      100% {
        opacity: 0;
        visibility: hidden;
      }
    }
    
    </style>
    
    <script>
      function addPopup() {
        const newDiv = document.createElement('div');
        newDiv.classList.add('popup');
        newDiv.innerHTML = "ポップアップテスト";
        document.body.appendChild(newDiv);
      }
    </script>
</head>
<body>

<button onclick="addPopup()">ポップアップ追加</button>

</body>
</html>
```