Animated Page Transitions in React
Tags: codenewbie, beginners, react, css
Published: 2021-02-17 17:31:28

Animated transitions between pages can make your single page web app more engaging, and keep users interested in the app and maintain context of what they were looking at instead of waiting for a page to load. Animations have been used on the web for some time to improve effectiveness, simplify the user experience, and to make the content more engaging and fun. Have you ever scrolled through a website and wondered how to make a website animate between pages? Yeah, so have I. This post is meant to show you how easy it is to create a simple animation between routes in a single page web app using React.

[Take a look at how Material Design describes the importance of animation.](https://material.io/design/motion/the-motion-system.html#principles)
![Example Page Transition Animations from Material Design: https://material.io/design/motion/the-motion-system.html#principles](https://imgur.com/zQmdP94.gif)


### ReactCSSTransitionGroup API - Simple CSS Transitions
The React team supports a community-maintained API add-on component for React called React CSS Transition Group, which allows an easy way to add CSS animations to React components. The `ReactCSSTransitionGroup` is a component of the larger `react-transition-group` package, and is useful to defining CSS classes for stages of a component animation cycle, allowing you to apply CSS styling and animation transitions on stages such as `.page-transition-enter` or `.page-transition-leave`. I will be using `ReactCSSTransitionGroup` in my demo, to make a quick and easy entrance and exit animation for two pages in a React app via CSS transitions.

##### Add ReactCSSTransitionGroup as component enveloping Routes
We first have to include `ReactCSSTransitionGroup` into our component, and then we will wrap our Routes around with this component, defining a transitionName so we can access the styles in CSS later. The transitionName we will choose for this demo is `page-transition`.
```
// React
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

class Layout extends React.Component {
  render() {
    return (
      <div>
        // Add ReactCSSTransitionGroup to Routes with name: 'page-transition'
        <ReactCSSTransitionGroup component="div" transitionName="page-transition">
           <Routes />
        </ReactCSSTransitionGroup>
      </div>
);}}
```

##### Apply CSS Class Names to Routes
We then have to add the CSS class names we would like each Route component to include, so we can style them correctly and apply our animations.
```
// Setting Home Route up with "transition" CSS class
class Home extends React.Component {
  render() {
    return (
      <div className="transition blue">
           <Link to="about">
      	      <h1>NEXT</h1>
           </Link>
      </div>
    );
}}

// Setting About Route up with "transition" CSS class
class About extends React.Component {
  render() {
    return (
      <div className="transition coral">
          <Link to="home">
            <h1>LAST</h1>
          </Link>
      </div>
    );
}}
```

### CSS
The CSS we need to style includes the display of each component while they are active, along with the CSS classes for each transition stage of the `ReactCSSTransitionGroup` we would like to animate. Remember, we chose `page-transition` as our `ReactCSSTransitionGroup` transitionName, so the API will look for classes with that associate className to run during the transition cycle. We just want to animate as the page enters and leaves, so will style both the `.page-transition-enter` and `.page-transition-leave` classes together for simplicity.

```
//CSS
$time: 2s;
$easing: ease-in-out;

// Style components how they should appear when active
.transition {
  width: 100%;
  height: 100%;
  
  div {
    transition: all $time/2 $easing;
    width: 99vw;
    height: 97vh;
    margin: .5% auto;
  }

  h1 {
    transition: all $time/2 $easing;
    transform: translateY(0);
  }

  &.coral > div {
    background: #f34044;
  }

  &.blue > div {
    background: #405efb;
  }
}

// Style page transition animations under the ReactCSSTransitionGroup name we chose: 'page-tansition' 
.page-transition-enter, .page-transition-leave {
  transition: opacity $time $easing;
  opacity: 0;
  position: absolute;

  div {
     margin-top: 35%;
     height: 0;
     opacity: 0;
     width: 20vw;
  }

  h1 {
    transform: scale(.8);
    opacity: 0;
  }
}

.page-transition-enter.page-transition-enter-active {
  opacity: 1;
}

.page-transition-leave.page-transition-leave-active  {
  opacity: 0;
}
```

### Example Application
I created a demo of our application on CodePen so you have a full example of the code. Feel free to steal some or all of the code from this [CodePen example](https://codepen.io/lukekyl/pen/XWNMWzL), but note you will likely need to adjust the styling to fit your own application and what you would like it to do. 

{% codepen https://codepen.io/lukekyl/pen/XWNMWzL default-tab=result %}



### Conclusion
I am just touching the surface when it comes to animated page transitions in React, but it has been exciting to learn so far, and `ReactCSSTransitionGroup` makes it easy to implement basic CSS animations and transformations on a React component's lifecycle. When done correctly, adding animations to page transitions can help improve your apps user experience, making it more fun to use, and giving it a more responsive and faster feel. 

##### Additional Resources for using ReactCSSTransitionGroup
- [CSS-Tricks: Animating Between Views in React](https://css-tricks.com/animating-between-views-in-react/)
- [Dev post by Jose Felix: Page Transitions In React](https://dev.to/joserfelix/page-transitions-in-react-1c8g)
- [React Docs: Animation Add-Ons](https://reactjs.org/docs/animation.html)
- [React Community: React Transition Group](http://reactcommunity.org/react-transition-group/)


**Have you used Animated Page Transitions in your React project?**
Comment if you have used ReactCSSTransitionGroup, have another favorite library, or have any suggestions for improvements!