React Animations with React Transition Group in practical examples
In this tutorial we will learn how to build web animations from scratch using React and the React Transition Group library. React Transition Group is a small library that allows us to create powerful animations and transition in our React applications. We will start with simple animation and then the complexity will increase with each example.
1. Horizontal slide animation
Now let’s examine how we built this simple animation. Here is the markup:
<CSSTransition
in={this.state.boxVisible}
unmountOnExit
timeout={400}
classNames="slide"
>
<div className="box" />
</CSSTransition>
We used the CSSTransition component provided by the library, to wrap the element that we want to animate. The CSSTransition is not the only component that the library provides – we have also Transition, TransitionGroup etc. The main feature of CSSTransition is that it’s adding CSS classes at each stage of the animation(there are 4 main stages). It also has the in prop which allows to pass boolean and indicate when to show and hide the animated item. With unmountOnExit we indicate that the child component should be unmounted after the exit transition has ended The timeout pop defines the duration of the animation(basically the time for switching the CSS classes). By the classNames prop we add prefix to each of these classes so that we can target them and add styling for each stage. Here is the styling for the the horizontal slide animation:
.slide-enter {
opacity: 0;
transform: translateX(-500px) scale(0.6);
}
.slide-enter-active {
opacity: 1;
transition: all 400ms ease-out;
transform: translateX(0) scale(1);
}
.slide-exit {
opacity: 1;
}
.slide-exit-active {
opacity: 0;
transition: all 400ms ease-in;
transform: translateX(500px) scale(0.6);
}
As you can see, the stage names are pretty intuitive – enter, enter-active, exit, exit-active.
In enter we add the initial styling used before the animation has started. In enter-active we are styling the actual appearance of the element, this is also the place where we add the transition CSS property – duration, delay, easing.
The exit stage is where we add the initial styling before the exit animation has started. As you probably guessed – the exit-active is where we define the styling for the animated dissapearing of the element. As a rule of thumb – we add the transition CSS property in the active classes.
By having full control over the animation stages you can create truly rich and powerful animations.
2. Animated modal
In this more practical example we’re using the same technique. We define all the transition styles using the show-up prefix and the magic happens.
3. Animated list insertion and removal
This example is a bit more complex. Here we use more advanced CSS techniques to achieve the sliding effect for each of the list items when it’s inserted or removed. You may also notice that we use a new component – TransitionGroup. When we animate lists or just grouped items we should always wrap them in TransitionGroup.
Let’s examine this transition in more details:
<CSSTransition
key={item.name}
timeout={500}
classNames="slide-down"
unmountOnExit
>
<div className="list-card-wrapper">
<div
className="list-card"
onClick={() => this.removeFromList(index)}
>
<span>{item.name}</span>
</div>
</div>
</CSSTransition>
.list-card-wrapper {
width: 100%;
overflow: hidden;
max-height: 120px;
display: flex;
justify-content: center;
will-change: true;
}
.list-card {
transition: all 1s;
width: 98%;
cursor: pointer;
height: 100%;
border: 1px solid #ccc;
margin: 20px 0;
padding: 30px 0;
overflow: hidden;
justify-content: center;
align-items: center;
flex-grow: 1;
display: flex;
}
.slide-down-enter {
opacity: 0;
max-height: 0;
}
.slide-down-enter-active {
transition: max-height 500ms ease-out, opacity 300ms ease-out;
opacity: 1;
max-height: 120px;
}
.slide-down-exit {
opacity: 1;
}
.slide-down-exit-active {
opacity: 0;
transition: max-height 500ms ease-out, opacity 300ms ease-out;
max-height: 0;
}
.slide-down-exit-active span {
text-decoration: line-through;
}
The first thing to point out is that each of the list items is wrapped in an element with className list-card-wrapper. The reason for that is because of the way the box-model works. In this particular case we’re animating the list item using the max-height property. As you probably know, the padding is also included in the overall height of an element, so if we don’t animate the padding, the animation looks pretty wonky as the padding remains and dissapears suddenly. One way to approach is to handle this, is to animate the padding property which I would not recommend. I personally prefer to wrap the whole list item in an element without any padding and just animate its max-height property. Don’t forget to add opacity:hidden to the list-item-wrapper otherwise the list item will go outside of it.
I hope that now you have better understanding of the way we animate React components with react-transition-group . If you want to learn more, you can always install the library in your project and start experimenting it. Enjoy!