みかづきブログ・カスタム

基本的にはちょちょいのほいです。

styled-componentsでCSSアニメーションを使ってもうまくいかない場合は記述位置を確認する 🔍

最近は、もっぱらNext.js + styled-componentsでウェブサイトを作っております。
そんな折、動作原理を考えたら当然の挙動なのですが、一瞬ハマったのでメモを残します。

ことの発端

const BtnWrapper = styled.div`
  position: relative;
  width: 44px; height: 44px;
  background: red;
  transition: background .4s ease-in-out;

  &[data-is-select="true"] {
    background: blue;
  }
`;

こんな感じのコードを書きまして、PropsでisSelectを渡して状態を切り替えようとしていたのですが、

import styled from 'styled-components';

export default function Btn({ isSelect }: {
  isSelect: boolean;
}) {
  const BtnWrapper = styled.div`
    position: relative;
    width: 44px; height: 44px;
    background: red;
    transition: background .4s ease-in-out;

    &[data-is-select="true"] {
      background: blue;
    }
  `;

  return (
    <Wrapper
      data-is-select={ String(isSelect) }
      className="btn-menu"
    />
  )
}

こんな感じで書くと、CSSアニメーションが効きませんでした。

「あれ?backgroundってアニメーションできなかったかな?」と思い、ディベロッパーツール経由でdata属性を付けたり消したりすると、しっかりアニメーションします。

原因

styled-componentsをfunctionの中で定義しているのが原因です。
functionの中は再レンダリングが走った際に実行されてしまうので。

なので、CSSアニメーションを有効にしたい場合は、

import styled from 'styled-components';

const BtnWrapper = styled.div`
  position: relative;
  width: 44px; height: 44px;
  background: red;
  transition: background .4s ease-in-out;

  &[data-is-select="true"] {
    background: blue;
  }
`;

export default function Btn({ isSelect }: {
  isSelect: boolean;
}) {
  return (
    <Wrapper
      data-is-select={ String(isSelect) }
      className="btn-menu"
    />
  )
}

という感じで、functionの外で定義してあげましょう。

的なことがissueに書いてありました。

github.com