📌

Next.jsのCSSアニメーションの連続トリガー、最適解がわからない

2022/08/13に公開

前回トーストのスタイリング+アニメーションの記事を書いた。この記事にはトリガーがない。

https://zenn.dev/neko/articles/18295386662744

例えばブログ記事の保存ボタンを押した時に「保存しました」を出したい。つまり何度も出したい。CSSのアニメーションのトリガーはanimationが認識された時点、つまり開始時。

アニメーションを始める時にはこれでいいが、2回目にトリガーしたい時は一度CSSをきれいにしてもう一度変更を加える必要がある。やってられない。

そこで思い切ってコンポーネントごと抜いたり入れたりすることにした。

export function Toast({ text }) {
  return (
    <div className="toast animate-toastin">{ text }</div>
  )
}

export default function Home() {
  const [val, setVal] = useState(false);
  function handle() {
    setVal(true);
    // ここが気持ち悪い。CSS側の時間とズレるともちろん正しく動かない。
    setTimeout(_ => setVal(false), 3000);
  }
  return (
    <>
      // このdivを押すとToastがトリガーされる
      <div onClick={ handle }>{ val.toString() }</div>
      { val ? <Toast></Toast> : <></> }
    </>
  )
}
.animate-toastin {
  animation-duration: 3s;
  animation-name: toastin;
}

.toast {
  @apply opacity-0 right-20 bottom-0 fixed shadow-xl py-4 px-8 w-min text-center bg-slate-800 rounded-lg font-bold text-white font-sans;
}

@keyframes toastin {
  0% {
    bottom: 0px;
    opacity: 0;
  }
  10% {
    bottom: 50px;
    opacity: 1;
  }
  90% {
    bottom: 50px;
    opacity: 1;
  }
  100% {
    bottom: 0px;
    opacity: 0;
  }
}

これでとりあえず作ってるけどみんなどうしてるんだろう。もちろん下のようなテクニックがあるのは知ってるんです。でもやたら長い呪文を書きたくないのです。。

https://zenn.dev/junki555/articles/24da1f474a7dfab48865

Discussion