Examples with React and CSS transitions

How do we use CSS transitions in react?

Progress bar example (Codepen)

Let’s start off with a progress bar first. Whenever we update the progress bar, it shouldn’t jump to its new progress indicator. Instead we want to see a gradual change to the progress bar’s width until it reaches its current progress status.

Progress bar component

In the progress bar component, the width gets changed whenever the progress is updated. A progress of 20% will result in 20% width of the progress bar.

const ProgressBar = ({ progress }) => (

<div id=”progressbar”>

<div className=”progress” style={{ width: progress + ‘%’ }} />

</div>

)

ProgressBar.css

.progressbar .progress {

transition: width 100ms ease-in-out;

}

Without CSS transitions whenever the progress bar updates, it would expand to its new width immediately. Now, every time the width changes, it will transition to the new width in 100ms.

You can explore the progress bar example a bit further in codepen.

Change the length of the animation Change the timing function (ease-in, linear) Update the progress bar multiple times before the animation has finished. Does it run smoothly?

Navigation bar sliding in and sliding out

Navigation bar slide in / slide out

Finally let’s get to the navigation bar. If you are used to jQuery animations, you would use the following imperative approach: $(“#navbar”).slideIn(). The difference to jQuery is that react is declarative. i.e. what does the navigation component look like when it is visible. In this case, when the navigation bar is visible the slideIn class is applied, when it is not visible the slideOut class is applied.

The Navigation Bar Component (on codepen)

const Navbar = ({ visible }) => (

<div id="navbar" className={visible ? 'slideIn' : 'slideOut'}>

</div>

)

NavigationBar.css

#navbar {

width: 220px;

transform: translateX(-220px);

transition: transform 400ms ease-in;

} #navbar.slideIn {

transform: translateX(0);

} #navbar.slideOut {

transform: translateX(-220px);

}

Codepen example

We use the transform property in CSS to position the navigation bar. A translation of -220px on the x-axis means that it will be completely out of view when the navigation bar is added to a page on the left. .slideIn will move the element back into the page. .slideOut will move the element completely out of view again.

With the CSS transition, we tell the browser whenever there is a change to the transform property (in this case when the element’s position is changed), animate the change over 400ms. And voila, we have a simple sliding navigation bar with a few lines of code.

Why start with CSS transitions?

Easy to write

If there’s no need for any external library, there’s no need to learn yet another API. By just understanding the basic components of CSS transitions, you will be able to accomplish quite a bit.

Interruptible

In the above case, all the animations were interruptible. If you click multiple times on the navigation bar, it will slide in and stop its slide in when you click again. That is we did not have to wait for the animation to complete, before interacting with the app and giving it a new animation.

Performance

Browsers are getting better and better at handling CSS transitions. Specifically if you transition the following properties: transform, opacity. This means that the browser does not have to do a lot of work (no need to repaint other elements). Smooth animations on desktop and mobile are possible.

CSS transitions drawbacks

Browser support

CSS transitions don’t work with older browsers, such as IE 9. The graceful fallback here is that no animation is displayed, but the app will still function.

Advanced animations

More advanced animations such as chaining and staggering gets really difficult or near impossible with only CSS transitions and keyframes. Yes, you will need to use something else then. No silver bullets, not even with CSS ;)

In Summary

Rather than reaching out to the next animation library the next time, check if you can solve it with CSS transitions. You might be surprised that it accomplishes just what you need.

External references:

… but, but what about…

What about unmounting animations? How can I ensure silky smooth animations? When do I need to use react-motion / ReactCSSTransitionGroup and how?

I will explore some of these in upcoming posts. You can keep updated when the next one comes out