サイトを作っていると、ダイアログを表示させてユーザーに何かしてほしいことがときどきある。

そんなニーズに遭遇したのでサンプルを作ってみた。

「Open dialog」のボタンを押すと背景が暗転し、ダイアログが出現する。

「Close dialog」を押すと元に戻る。

サンプルコードはこちら。

ダイアログにはボタンしかないけど、ここに何かしらユーザーに期待する操作を促すテキストインプットやらボタンやらが配置される想定。

See the Pen ボタンを押してダイアログを表示させるサンプル by Makoto Ohnami (@zohnami) on CodePen.

まず、cssにアニメーションの設定を書いておく。

.animation_fade_inがダイアログ登場時に実行されるアニメーションクラスで、.animation_fade_outがダイアログを閉じるときに実行される。

easingはかなり適当。この辺の使い方を理屈を基準に調整できるようになりたいけど全くよくわかわらない。雰囲気でやってしまっている。

/* ここからアニメーション設定 */
@keyframes fadeIn {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

.animation_fade_in {
  animation-name: fadeIn;
  animation-duration: 0.2s;
  animation-timing-function: ease-in-out;
  animation-fill-mode: forwards;
  opacity: 0;
}

@keyframes fadeOut {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

.animation_fade_out {
  animation-name: fadeOut;
  animation-duration: 0.2s;
  animation-timing-function: ease-in-out;
  animation-fill-mode: forwards;
  opacity: 1;
}

そしてjsにはイベント発火を設置していく。

ポイントはダイアログを閉じるとき。is-hiddenクラスの追加はアニメーション終了時に追加していること。

animeationendのイベントを拾って、is-hiddenを追加している。

そうしないと、アニメーションが終了する前にis-hiddenが当たって、フェードアウトのアニメーションが途中でかき消されてしまう。

contains('animation_fade_out')でフィルタリングをしているのはanimation_fade_inも対象になってしまうと、ダイアログがオープンした直後に再びis-hiddenが当たってしまってダイアログが消えてしまうから。

const openButton = document.getElementById('open_button')
openButton.addEventListener('click', () => {
  const screen = document.getElementById('screen')
  screen.classList.remove('is-hidden', 'animation_fade_out')
  screen.classList.add('animation_fade_in')
})

const closeButton = document.getElementById('close_button')
closeButton.addEventListener('click', () => {
  const screen = document.getElementById('screen')
  screen.classList.remove('animation_fade_in')
  screen.classList.add('animation_fade_out')
})

const screen = document.getElementById('screen')
screen.addEventListener('animationend', (event) => {
  if (event.currentTarget.classList.contains('animation_fade_out')) {
    event.currentTarget.classList.add('is-hidden')
  }
})

このくらいだったらjQueryとかReactとか使わなくても素のjsでいけますね。

この記事の環境情報

  • HTML,CSS,javascript
  • 月曜の朝