How to Easily Animate Your React Components On Click with CSS Keyframes!🎆
Tags: react, css, javascript, gatsby
Published: 2020-02-02 22:29:48

## Introduction
Over the weekend, I've started work on a personal website built through Gatsby. I got started with their fantastic and beginner friendly tutorials, available [here](https://www.gatsbyjs.org/tutorial/).

As I got going, I wanted to bring my pages to life by animating components and elements on my screen.
While there are fantastic plugins for Gatsby and React, as well as other JavaScript libraries, I had no prior experience with CSS animations, and wanted to learn for myself. 

I'm pretty happy with the results, and thought it might be a good idea to share the technique I used here!


## The Base Component
For this post, we'll use a basic _img_ element as our component:

_animated-image.js_
```javascript
import React from 'react'
import styles from './animated-image.module.scss'

const Image = () => (
  <img
    className={styles.image}
    src="https://source.unsplash.com/random/400x200"
    alt="randomised!"
  />
)

export default Image

```
_animated-image.module.scss_
```css
.image {
  display: block;
  margin: 0 auto;
}

```
This component just retrieves a random 400x200 image whenever it's called. I happen to be using SCSS, but it doesn't make a difference, the technique works in CSS too. The SCSS module for this component just centre aligns the image, to look like so:
![how the component looks on screen](https://dev-to-uploads.s3.amazonaws.com/i/dxwbn4daexnqawwdcq9y.png)
If you're unfamiliar with Gatsby CSS/SCSS/SASS modules, essentially it's just a way to localise stylesheets to components or web-pages.

## Animating Our Component

Lets say, we want our component to 'wobble' when our user interacts with it. 
By 'wobble', I mean something basic like the component swinging to the left and right a little bit, and stopping rather quickly.

In our stylesheet, we can utilise @keyframes to describe our wobbling process!

@keyframes allow us to storyboard the animation process.

We can describe the transformations of the target element at any point of the animation cycle. 

The syntax for a basic @keyframes, is so:

 - @keyframes animation-name { step { transformation } }

In replace of 'step', we can use 0-100% to mark the animation frame, or use 'from' and 'to' to show a transition.

For our wobble example, lets use something like this:
```css
.image {
  display: block;
  margin: 0 auto;
}
.image:focus, .image:hover {
  animation: wobble 1s 1;
}

@keyframes wobble {
  25% {
    transform: rotate(15deg);
  }
  50% {
    transform: rotate(-30deg);
  }
  75% {
    transform: rotate(5deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

```
Three things to note here:
1. We specified the transformations using the 'transform' attribute, along with one of many CSS transformation functions, rotate. This takes a single positive or negative deg value, to represent a clockwise or anti-clockwise angle.
2. We added a focus and hover pseudo-state listener to the image, which means when our user hovers over it, we'll see the animation!
3. We run our animation by specifying the name of the keyframe animation script, along with how long this animation should take to complete (in our case, one second), and finally how many times it should do so (this can also be infinite, to go on forever. In our case, only run once).

Let's test it out..

![Wobbling on hover](https://dev-to-uploads.s3.amazonaws.com/i/x4r330wezaaueoo76zci.gif)

#### Nice!

## Animation on Click with React
We've seen the animation working on the pseudo-states of elements, but how can we control animations from HTML/JS events? 

We may want animations on click, which isn't an option in CSS.

We can introduce a useState hook to our component to overcome this. 

useState is a React Hook that gives us simple getter/setter methods to control a value state in our component. The changes are rendered on the web-page as the values are updated!

_animated-image.js_
```javascript
import React from 'react'
import styles from './animated-image.module.scss'

const Image = () => {
  const [wobble, setWobble] = React.useState(0)
  return (
    <img
      className={styles.image}
      src="https://source.unsplash.com/random/400x200"
      alt="randomised!"
      onClick={() => setWobble(1)}
      onAnimationEnd={() => setWobble(0)}
      wobble={wobble}
    />
  )
}
export default Image

```
Here we can see our wobble (getter) and setWobble (setter) methods use a value of 1 to indicate wobbling is in process, and 0 to indicate wobbling has stopped. 

While _wobble_ is not a valid HTML element attribute, React will render unknown properties as Element Data Attributes. Data Attributes allow us to store data in elements. 

Typically, data attributes shouldn't be used for content specific data, as that is what the Component State is used for. But a scenario like this using it as an animation marker is absolutely fine.
More information on HTML data attributes can be found [here](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes).

Now to update our CSS!
We want the animation to run when the wobble attribute is set to 1 only. To do this, we say: 
```css
.image {
  display: block;
  margin: 0 auto;
}
.image[wobble='1'] {
  animation: wobble 1s 1;
}

@keyframes wobble {
  25% {
    transform: rotate(15deg);
  }
  50% {
    transform: rotate(-30deg);
  }
  75% {
    transform: rotate(5deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

```
The square brackets in CSS matches attributes by the name supplied. In this case, the CSS condition is any 'image' class with a wobble attribute value of '1'.

__That's it!__

## The End Result
![Wobble on click!](https://dev-to-uploads.s3.amazonaws.com/i/o8bot7pxr45os7khp6c1.gif)

Perfect! We can see the animation occurs when we click the image, and we can also observe the wobble attribute being updated, controlling when the animation occurs.

## Conclusion

I hope this may of been some interest to you, and to demonstrate that CSS animations can be easy and effective at bringing your web applications to life!

This was my first article, go easy on me! If you liked it, or have any other feedback at all, please free to let me know. Thanks!😊

![Me wobbling!](https://dev-to-uploads.s3.amazonaws.com/i/11707uhc0db78jeffrck.gif)