ReactとTailwindCSSでアニメーションを実装しようとして少し詰まったのでメモ。
「ボタンが押されたら1秒かけて文字の不透明度を0から1にする」というアニメーションは下記のようにすれば実現できます。
import { useState } from "react";
export default function Home() {
const [animationStart, setAnimationStart] = useState(false);
return (
<>
<button
onClick={() => {
setAnimationStart(true);
}}
>
サンプルボタン
</button>
<div
className={`transition-all duration-1000 ease-linear ${
animationStart ? "opacity-100" : "opacity-0"
}`}
>
サンプル
</div>
</>
);
}
「サンプル」のdivタグにtransition-all duration-1000 ease-linear
でアニメーションが完了する時間や進行割合などを指定しています。
さらに、animationStart ? "opacity-100" : "opacity-0"
でanimationStart
は初期表示時はfalseなので、opacity-0
が適用されて文字列「サンプル」は初期表示時は表示されません。
「サンプルボタン」が押されたらanimationStart
がtrueになり、「サンプル」のdivタグのclassNameがopacity-0
からopacity-100
になるので、1秒かけて文字列「サンプル」が表示されます。
アニメーションをしたい要素が常にDOMに存在すれば上記のような書き方でOKですが、問題なのは下記のような場合です。
import { useState } from "react";
export default function Home() {
const [animationStart, setAnimationStart] = useState(false);
return (
<>
<button
onClick={() => {
setAnimationStart(true);
}}
>
サンプルボタン
</button>
{animationStart && (
<div
className={`transition-all duration-1000 ease-linear ${
animationStart ? "opacity-100" : "opacity-0"
}`}
>
サンプル
</div>
)}
</>
);
}
上記のコードでは、animationStart
がtrueになるまでは「サンプル」のdivタグはDOMに存在せず、trueになると初めてdivが生成されます。
この場合、アニメーションが適用されずに即座に最終状態が表示されるようです。
※ChatGPTに聞きました
じゃあどうするかと調べたら、CSSのanimation
とkeyframes
を使用したら実現できました。
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: "jit",
darkMode: false,
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
keyframes: {
sample: {
from: { opacity: 0 },
to: { opacity: 1 },
},
},
animation: {
sample: "sample 1s linear",
},
},
},
plugins: [],
};
import { useState } from "react";
export default function Home() {
const [animationStart, setAnimationStart] = useState(false);
return (
<>
<button
onClick={() => {
setAnimationStart(true);
}}
>
サンプルボタン
</button>
{animationStart && <div className={"animate-sample"}>サンプル</div>}
</>
);
}
tailwind.config.jsにanimation
とkeyframes
を定義しています。
animationにはアニメーションの名前、アニメーションの秒数、進行割合を指定しています。
keyframesにはアニメーションの始まりと終わりを定義しています。
ReactのコンポーネントではdivタグのclassNameにanimate-sample
を指定することにより、tailwind.config.jsで定義したアニメーションのクラスが適用されます。
これにより、animationStart
がfalseの間はdivタグはDOMに存在せず、trueになったらdivタグが生成され、かつ1秒かけて「サンプル」の文字が表示されるアニメーションが実現できました!
最初は「React TailwindCSS アニメーション」みたいな感じで調べていて、間違ったアプローチをしていたので少し詰まりました。
「display none アニメーション CSS」みたいな感じで調べたら今回の解決法に行きつきました。
IT技術ブログ
↓↓「にほんブログ村」のランキングに参加しています。少しでも面白い、参考になったとか思われたらポチッとしていただけると嬉しいです!
