DEV Community

loading...

CSS Animations with Styled Components

Mario
Software Engineer from Vienna, Austria. Building things, mainly in JavaScript.
Originally published at mariokandut.com on ・5 min read

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

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);
  }
`;
Enter fullscreen mode Exit fullscreen mode

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;
`;
Enter fullscreen mode Exit fullscreen mode

Then we return the styled component.

render(<Rotate>I am rotating </Rotate>);
Enter fullscreen mode Exit fullscreen mode

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

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

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;
`;
Enter fullscreen mode Exit fullscreen mode

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%;
}
Enter fullscreen mode Exit fullscreen mode

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%;
  }
`;
Enter fullscreen mode Exit fullscreen mode

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 );
  }
`;
Enter fullscreen mode Exit fullscreen mode

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

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

.animated-heart {
margin-top: 2rem;
position: relative;
width: 100px;
height: 100px;
animation: heartBeat 1s infinite;
}
.animated-heart:before,
.animated-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%;
}
.animated-heart:after {
left: 0;
transform: rotate(45deg);
transform-origin: 100% 100%;
}

@keyframes heartBeat {
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 ); }
}

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

Discussion (0)