React + styled-components で CSS の transition を使う


React + styled-components を触っている中で、スライドするボックスをどう作るかを考える機会がありました。

そこで、CSS の transition プロパティを、React + styled-components でどう使うかを調べてみたので、その記録を残しておきます。

CSS の transition プロパティについて

transition - CSS: カスケーディングスタイルシート | MDN

transition プロパティでは、そのプロパティを指定した要素における、2つの状態間の変化を定義することができます。
2つの状態の定義の仕方は、:hover:active といった擬似クラスや、自分で設定したクラスに定義する形で表現します。

今回は、transform プロパティの translateX() を使い、要素の位置を左右にずらした状態を2つ定義し、その遷移で要素の左右移動をさせてみる例を考えます。

サンプル

ボタンを押すことで左右にボックスがスライドするという簡単なサンプルを作ってみました。

① クラスの付け替え

まず単純にボタンを押した状態を state で定義しておき、その状態でクラスのつけ外しをする方法でやってみました。

See the Pen HoverDivSampleByAddingClass by Masayuki Goto (@gotchane) on CodePen.

.is-slided の CSS に transform プロパティを定義しておき、クラスをつけ外しすることで状態遷移させています。

② styled-components の css 定義内で切り替える

上記でも実現できたのですが、styled-components を使っているのにわざわざクラスをつけるのは違和感がありました。
どうせなら自前のクラスをつけないで実現したいと思い、調べた方法がこちらです。

See the Pen HoverDivSampleByProps by Masayuki Goto (@gotchane) on CodePen.

styled-components の CSS 定義に props でボタンの状態を渡し、translateX 内の数値を変化させることで状態遷移させています。

何故上記の方法で transition が利用できるのでしょうか?

ブラウザの開発者コンソールで調べてみたところ、styled-components で生成された要素に付加されているハッシュ値のクラス名が、props が切り替わるごとに変わることで、2つの状態をそれぞれ定義できていたようです。

ボタン押す前

styled-components によって動的にクラスが割り当てられている

<div class="sc-bwzfXH dbpADZ">...</div>
.dbpADZ {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 200px;
    height: 100%;
    transform: translateX(0px);
    background: pink;
    padding: 15px;
    transition: all 0.3s ease-out 0s;
}

ボタン押した後

  • .dbpADZ.bIxbAR に変わっている
  • translateX(0px)translateX(200px) に変わっている
<div class="sc-bwzfXH bIxbAR">...</div>
.bIxbAR {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 200px;
    height: 100%;
    transform: translateX(200px);
    background: pink;
    padding: 15px;
    transition: all 0.3s ease-out 0s;
}

補足:React の render 内で styled-components を定義すると transition がうまく動かないので注意

最後に補足として、styled-components のコンポーネントを React コンポーネントの render() 内で定義するとどうなるでしょうか?
そのサンプルがこちらです。

See the Pen HoverDivSampleByPropsInRender by Masayuki Goto (@gotchane) on CodePen.

React のコンポーネントは、props が切り替わると再レンダリングされるので、その度に styled-components のコンポーネントも再レンダリングされています。
サンプルを載せましたが、状態遷移中の描画が一瞬抜け落ちる挙動になってしまうようです。(styled-components の issue でも話題に上がっていました)

transition を 使う場合、 styled-components のコンポーネント定義は、React コンポーネントの render() 内で行わない方が良さそうですね。

参考