🫥
【React】CSS Modules + CSSTransitionを使ってtransition単位でアニメーションを実装する
背景
業務の中でreact-transtion-groupのCSSTrantionをCSSModules
で実装する方法を調査しました。
実装方法がなかなか見つからなかったので、備忘録として残しておきます。
実装方法
準備
ボタンをクリックした時に、アニメーションさせるような実装を簡単に書いてみます
src/App.js
import styles from './App.module.scss';
import { CSSTransition } from 'react-transition-group';
import { useState } from 'react';
function App() {
// 表示、非表示用のstate
const [inProp, setInProp] = useState(false)
return (
<div className={styles.container}>
<div className={styles['animation-content']}>Fade Animation</div>
<div className={styles['button-content']}>
<button onClick={() => {
setInProp(!inProp)
}}>
クリック
</button>
</div>
</div>
)
}
export default App;
(一応、scssも記述します)
src/App.module.scss
.container {
width: 100%;
height: 80vh;
justify-content: center;
align-items: center;
.animation-content {
background: orange;
border-radius: 20px;
margin: 200px auto 0;
width: 200px;
height: 200px;
text-align: center;
line-height: 200px;
font-size: 20px;
color: white;
}
.button-content {
margin-top: 20px;
text-align: center;
}
}
上記の実装で見た目はこんな感じになっています。
ライブラリのインストール
react-transition-groupを追加します。
npm install react-transition-group --save
アニメーション追加
fadeのアニメーションを追加していきます。
まず、fade用のCSSmodulesファイルを準備します。
src/styles/transitions/fade.module.scss
// 表示時アニメーション開始時の状態
.enter {
opacity: 1;
}
// 表示時アニメーション中の状態
.enterActive {
opacity: 0;
transition: opacity 500ms;
}
// 表示時アニメーション終了時の状態
.enterDone {
opacity: 0;
}
// 非表示アニメーション開始時の状態
.exit {
opacity: 0;
}
// 非表示アニメーション中の状態
.exitActive {
opacity: 1;
transition: opacity 500ms;
}
// 非表示アニメーション終了時の状態
.exitDone {
opacity: 1;
}
app.js
にCSSTransition
を追加していきます。
src/App.js
import styles from './App.module.scss';
import fade from './styles/transitions/fade.module.scss';
import { CSSTransition } from 'react-transition-group';
import { useState, useRef } from 'react';
function App() {
const [inProp, setInProp] = useState(false)
const nodeRef = useRef(null)
return (
<div className={styles.container}>
{/* ↓ fade用のstylesを設定 */}
<CSSTransition in={inProp} timeout={500} classNames={fade} nodeRef={nodeRef}>
<div className={styles['animation-content']} ref={nodeRef}>Fade Animation</div>
</CSSTransition>
<div className={styles['button-content']}>
<button onClick={() => {
setInProp(!inProp)
}}>
クリック
</button>
</div>
</div>
)
}
export default App;
CSSTransition
で設定しているプロパティとしては、下記の通りです。
in: 表示、非表示を切り替えるためのstateを設定
timeout: アニメーションが完了するまでの時間を設定
classNames: アニメーション用のスタイルを設定
classNamesでfade
を設定することで、fadeで設定したclassNameが展開されて、
classNames={{
enter,
enterActive,
enterDone,
exit,
exitActive,
exitDone,
}}
のようにアニメーションに必要なclassNameが設定されます。
結果
実際にアニメーションを動作させてみます。
うまくfadeアニメーションが実装されていることを確認できました!
追記
- CSSTransitionにnodeRefがついてない
- classNameがclassになっている
のミスがあったので、修正しました💦(2023/05/11)
Discussion