CSS Animations with Styled Components
© https://reactjs.org/

CSS Animations with Styled Components

Animations with @keyframes

By Mario Kandut

Styled components are visual primitives to style your React App and have plenty of great features, like the ability to write CSS right in the component, complexity reduction, faster loading, clear scope and other performance improvements.

This article is about CSS animations with the @keyframes property. CSS animations with @keyframes aren't scoped to a single component, but you still don't want them to be global to avoid name collisions.

Keyframes in Styled Components

💰 Start your cloud journey with $100 in free credits with DigitalOcean.

Styled components export a helper for dealing with CSS keyframes, which generates a uniques instance that can be used throughout the entire application.

Let's have a look at an example from the styled components docs.

We have to create the keyframes.

const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
`;

Create a component, that will rotate everything we pass in over two seconds

const Rotate = styled.div`
  display: inline-block;
  animation: ${rotate} 2s linear infinite;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;

Then we return the styled component.

render(<Rotate>I am rotating </Rotate>);

"Keyframes are not supported by react-native. Use the ReactNative.Animated API."

Keyframes are lazily injected when they're used. Hence, keyframes can take advantage of code-splitting, though you have to use the css helper for shared style fragments, see example from official docs.

const rotate = keyframes``;

// ❌ This will throw an error!
const styles = `
  animation: ${rotate} 2s linear infinite;
`;

// ✅ This will work as intended
const styles = css`
  animation: ${rotate} 2s linear infinite;
`;

Code: Beating Heart Example

Let's have a look at a concrete example for animation with keyframes. We want to make a beating heart animation.

First we need a CSS heart shape to animate, we could use an SVG or make a heart shape with CSS. Since we already know how to make a heart with pure CSS, see Basic CSS shapes, we can adapt the CSS.

.heart {
  position: relative;
  width: 100px;
  height: 90px;
}
.heart:before,
.heart:after {
  position: absolute;
  content: '';
  left: 50px;
  top: 0;
  width: 50px;
  height: 80px;
  background: red;
  border-radius: 50px 50px 0 0;
  transform: rotate(-45deg);
  transform-origin: 0 100%;
}
.heart:after {
  left: 0;
  transform: rotate(45deg);
  transform-origin: 100% 100%;
}

We adapt the CSS for styled-components:

const Heart = styled.div`
  position: relative;
  width: 100px;
  height: 90px;
  &:before,
  &:after {
    position: absolute;
    content: '';
    left: 50px;
    top: 0;
    width: 50px;
    height: 80px;
    background: red;
    border-radius: 50px 50px 0 0;
    transform: rotate(-45deg);
    transform-origin: 0 100%;
  }
  &:after {
    left: 0;
    transform: rotate(45deg);
    transform-origin: 100% 100%;
  }
`;

We create the keyframes for the animation:

const heartBeat = keyframes`
  0%
  {
    transform: scale( .75 );
  }
  20%
  {
    transform: scale( 1.1 );
  }
  40%
  {
    transform: scale( .75 );
  }
  60%
  {
    transform: scale( 1.1 );
  }
  80%
  {
    transform: scale( .75 );
  }
  100%
  {
    transform: scale( .75 );
  }
`;

We add the animation property to our styled Heart and voila. We have a beating heart.

const AnimatedHeart = styled(Heart)`
  animation: ${heartBeat} 1s infinite;
`;

TL;DR

CSS animations with keyframes can be easily done with styled-components and the helper utility keyframes. The code is cleaner, not scattered around the application and more performant than other CSS solutions.

Thanks for reading and if you have any questions, use the comment function or send me a message @mariokandut. If you want to know more about React, have a look at these React Tutorials.

References (and Big thanks):

Styled Components, Matt Readout

Scroll to top ↑

We use cookies 🍪 to build a better website.! Close to accept or learn more.