💎

MUIでCSSアニメーションを設定する

に公開

始めに

ReactのUIライブラリの一つに Material UI がありますが、こちらを使ってアニメーションを設定する場合Transitionsに書かれているようなトランジションでアニメーションする方法しか載っておらず、CSSアニメーションの設定は見当たりませんでした。StackOverflowなどで調べたり検証コードを書いたりして設定方法が分かったので備忘録としてまとめました。

ちなみにトランジションのカスタマイズ方法は以下の記事にまとめておりますので興味があればご参照ください。

https://zenn.dev/numa_san/articles/e213d29e4cc227

MUIでCSSアニメーションを設定する方法

MUIはemotionを使っているため、emotionを使ったkeyframesの設定をして、そこで生成された変数を使用することでCSSアニメーションが設定できます。なお、emotionのコードはMUIのパッケージに再エクスポートしているようなのでMUIパッケージからimportすることができます。
またemotionのドキュメントでは文字列で書く方法をよく見かけますが、MUIのsx設定のようにオブジェクト形式で設定することも可能です。

https://emotion.sh/docs/object-styles

MUIでCSSアニメーションを設定する
import { Box, Stack } from '@mui/material';
import { keyframes, styled } from '@mui/material/styles';

// 文字列パターン
const spinAnimation = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
`;

// オブジェクトパターン
const doubleSpinAnimation = keyframes({
  from: {
    transform: 'rotate(0deg)',
  },
  to: {
    transform: 'rotate(720deg)',
  },
});

const StyledRotateBox = styled('div')(() => {
  return {
    width: 40,
    height: 40,
    backgroundColor: 'red',
    // styledコンポーネントにアニメーションを設定する
    animation: `${spinAnimation} 1s infinite ease`,
  };
});

const App = () => {
  return (
    <Stack spacing={2}>
      <StyledRotateBox />
      <Box
        sx={{
          width: 40,
          height: 40,
          backgroundColor: 'blue',
          // sx propに対して設定も可能
          animation: `${doubleSpinAnimation} 1s infinite ease`
        }}
      />
    </Stack>
  )
}

一応動くけどよくない実装

他にも一応sxの中にkeyframesを定義しても動きますが、アニメーション名がグローバルで登録されるため、同じ名前を再定義すると上書きされてしまうリスクがあります。このリスクを考えるとemotionのkeyframesで定義したものを使うのが良さそうです。

動きはするがオススメできない設定
import { Box, Stack } from '@mui/material';

const App = () => {
  return (
    <Stack spacing={2}>
      <Box
        sx={{
          '@keyframes spin': {
            from: {
              transform: 'rotate(0deg)',
            },
            to: {
              transform: 'rotate(360deg)',
            },
          },
          width: 40,
          height: 40,
          backgroundColor: 'orange',
          animation: 'spin 1s infinite ease',
        }}
      />
      <Box
        sx={{
          // sxで定義するとグローバルにアニメーションが設定され、上書きされる
          '@keyframes spin': {
            from: {
              transform: 'rotate(0deg)',
            },
            to: {
              transform: 'rotate(720deg)',
            },
          },
          width: 40,
          height: 40,
          backgroundColor: 'purple',
          animation: 'spin 1s infinite ease',
        }}
      />
    </Stack>
  )
}

終わりに

以上がMUIでCSSアニメーションを設定する方法でした。sx propでも何となく動いていたりしてちゃんとした方法が何なのか分からず手を出しづらい状況だったのですが、本腰入れて調べてやり方が確立出来て良かったです😊
最後に検証コードを以下に貼りますので興味がある方は是非ご参照ください。

参考

https://stackoverflow.com/a/63546822

GitHubで編集を提案

Discussion