【React】Emotionでクラスを動的に変化させたり、あれこれ試してみる
概要
前回、Emotionの書き方を忘備録として残した。
今回は色々試していこうかと思う。
とりあえず、Emotionのオブジェクトでまとめた書き方や、CSSのanimation
やtransition
によるアニメーションやクリックしたらアニメーションさせる、クラスを切り替えるなどやってみる。
また今回はオブジェクトスタイルではなく、ストリングススタイルで基本的には書いていく。
*Emotionを利用する理由としては、通常のCSSのように書けるのが良いと思ってるので。
アニメーション
まずはアニメーションをやってみる。
アニメーションはanimation
とtransition
の2つ。
animation
animation
の場合はkeyframes
をCSSで下記のように設定していた。
@keyframes animation{
0%{
margin-left: 0;
}
100% {
margin-left: 100%;
}
}
Emotionの場合、@keyframes
の代わりにkeyframes
を使って下記のように書く。
const moveX = keyframes`
0%{
margin-left: 0;
}
100% {
margin-left: 100%;
}
`
const anime = css`
background-color: yellow;
width: 50px;
height: 50px;
animation: ${moveX} 1s linear infinite alternate backwards;
`
const App = () => {
return (
<>
<div css={anime}></div>
</>
);
};
keyframes
を使ってアニメーションの開始・終了の状態を設定したら。
変数anime
のanimation
プロパティにanimation-name
にあたる${moveX}
と指定する。あとはdiv
要素にCSSとして指定する。
trasition
今度はtransition
について。
こちらもEmotionの書き方さえ分かれば通常のCSSと変わらない。
例えばロールオーバーしたらちょっと大きくなるアニメーションを付け加えたいとしたら下記のようにする。
const hoverTransition = css`
width: 50px;
height: 50px;
background-color: red;
margin-left:100px;
transition: transform 0.4s cubic-bezier(.47,1.64,.41,.8);
&:hover {
transform: scale(2, 2);
}
`
const App = () => {
return (
<>
<div css={hoverTransition}></div>
</>
);
};
その他の使い方
その他の使い方として、関数のようにして値を渡す方法や、クラスを追加する方法がある。
関数のように記述して引数を渡す
Emotionの場合、CSSを関数のように記述して引数を渡すことができる。
これによってクリックしたかどうかによって、背景色を変更するなどできる。
実際にクリックしたら背景色を変更する例。
ReactのuseState
を利用してtrue
:false
で色を変更してみる
const setBg = (flg) =>(
css`
background-color: ${flg ? "red" : "blue"};
width: 100px;
height: 100px;
cursor: pointer;
`
);
const App = () => {
const [isClick, setIsClick] = useState(false);
const bgChangeHandler = () => {
setIsClick(!isClick);
};
return (
<>
<div css={setBg(isClick)} onClick={bgChangeHandler}>
<p>背景色を帰る</p>
</div>
</>
);
};
これまでの通りcss
にクラスを設定するが、css={setBg(isClick)}
のようにuseState
で設したisClick
の値を引き渡すことができる。
あとは、CSSのbackground-color
の値を三項演算子でtrue
の場合は赤、false
の場合は青と切り替えることができる。
関数のように処理をしてCSSを返す
関数で引数で渡せるので、関数内で処理できる。最終的にretrun
でCSSを返してあげればいい。
- useStateで値を変更
- 値を関数に渡す
- CSSを返す
const [isColor, setIsColor] = useState("1");
const onChangeColor = (e) => {
setIsColor(e.target.value);
};
return(
<>
<label>
数値:<input onChange={(e) => {onChangeColor(e);}} type="number" max="3" min="1" />
</label>
<div css={cssFunc(isColor)}>
<p>このボックスの背景色を引数によって変更する</p>
</div>
</>
)
const cssFunc = (num) => {
let colors = "red";
if(num === "1") {
colors = "red";
}
if (num === "2") {
colors = "blue";
}
if (num === "3") {
colors = "yellow";
}
console.log(colors);
return [
css`
background-color: ${colors};
`
]
};
上記のように、useState
の値によってcssFunc
の中で条件分岐して背景色を変えるような動的な処理も可能となる。
*フォームのtype="number"
は文字列となるので注意。
クリックしたらクラスを追加する
今度はよくある、クリックしたらクラスを追加するパターン。
こちらも通常のReactでよく使われる三項演算子や論理積 (&&
)による式があっていれば処理するというやつです。
下記の例は論理積 (&&
)によるtrue
の場合は背景色の色のクラスを追加する例。
const borderBox =css`
border:2px solid #ff0000;
padding: 10px;
width: 100px;
cursor: pointer;
transition:all 0.3s
`
const addBgRed=css`
background-color: #ff0000;
`
const App = () => {
const [isClass, setIsClass] = useState(false);
const addClassHandler = () => {
setAddClass(!addClass);
};
return (
<>
<div css={[borderBox,isClass && addBgRed]} onClick={addClassHandler}>
<p>ボーダーボックス。<br/>クリックしたら背景色をつける</p>
</div>
</>
);
};
css
の部分でcss={[borderBox,isClass && addBgRed]}
となっている部分。
isClass
がtrue
の場合はaddBgRed
というクラスを追加する。
もちろん既存のborderBox
というクラスもあるので配列にしてある。
三項演算子も同じ。
もちろんこれまでのCSSと同じようにtransition
によるアニメーションもできる。
オブジェクトにしてみる
Emotionは、CSS in JSなのでJavaScriptのように書くことができるので、関連するCSSごとにオブジェクト形式でまとめることもできる。
例えば、2カラムのボックスのレイアウトをまとめた例。
const boxLyout = {
wrap: css`
display: flex;
width: 100%;
max-width: 600px;
margin: auto;
justify-content: space-between;
`,
box: css`
width: 45%;
border: 3px solid #333;
padding: 10px;
`,
ttl: css`
font-weight: bold;
font-size: 16px;
margin-bottom: 10px;
`,
article: css`
p {
&:not(:first-child) {
margin-top: 10px;
}
}
`,
};
const App = () => {
return (
<>
<div css={boxLyout.wrap}>
<div css={boxLyout.box}>
<h2 css={boxLyout.ttl}>タイトル</h2>
<div css={boxLyout.article}>
<p>ここは文章ここは文章ここは文章。</p>
<p>ここは文章ここは文章ここは文章。</p>
</div>
</div>
<div css={boxLyout.box}>
<h2 css={boxLyout.ttl}>タイトル</h2>
<div css={boxLyout.article}>
<p>ここは文章ここは文章ここは文章。</p>
<p>ここは文章ここは文章ここは文章。</p>
</div>
</div>
</div>
</>
);
};
上記のようにboxLyout
というオブジェクトを作成してまとめる事ができる。
もちろん、関数のように引数を指定することなども可能。
const boxLyout = {
box: (flg)=>(
css`
width: 45%;
border: 3px solid #333;
padding: 10px;
cursor: pointer;
background-color: ${flg && "red"};
`
)
};
まとめ
ざっとEmotionの使い方を勉強してきた。
あとは実践で学ぶしかない。
Discussion