CSS
Background Slider with react-transition-group
December 2, 2019First of all, what’s my motivation to write this article? I needed to use sliding background animation for a cool display on my website. I know there are some carousel components in the ecosystem but I couldn’t find a drag-and-drop solution to my situation. What I need is sliding background animation, when a different route is selected (yes, react-router
also exists!).
I encountered a few problems during this journey. Articles I found using react-addons-css-transition-group
which is moved to react-transition-group
according to the official documentation. Secondly, I struggled with new documentation of the package. I had few trial and error cases until I leaned back with satisfaction.
Maybe, this article will be your drag-and-drop solution in your projects. That’s why I’m writing right now. Let’s get started.
In my scenario, I want to change the background image with every route change. It can be done by using path specific images with react-router
. However, I want to add a smooth change between images. The solution is CSS transition but how can I force to animate background images programmatically?
First, I should tell when the transition happens to react-transition-group
. It happens when background.path
is changed. Background data of the demo is below:
{
path: "/",
src: "http://sorblog.com/wp-content/uploads/2018/10/javascript-autoclick.jpg"
},
{
path: "/react",
src: "https://cdn-images-1.medium.com/max/1200/1*jDIj2SKAE-Bp32owLoHDjw.png"
},
{
path: "/transition",
src: "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/09/1475177859css.jpg"
}
The important part is change of CSSTransition
’s key prop. When key changes, the current background goes into an exiting state and the incoming one goes into an entering state. You can see the transition in slow-motion (total transition duration 5000ms):
Below implementation express how it should be in action:
const Background = () => {
const location = useLocation();
const background = backgrounds.find(bg => bg.path === location.pathname); return (
<div>
<TransitionGroup>
<CSSTransition
classNames="slide"
timeout={{ enter: 1000, exit: 1000 }}
key={background.path}
>
<img
className="background"
src={background.src}
alt={background.path.slice(1)}
/>
</CSSTransition>
</TransitionGroup>
</div>
);
};
Last part is writing proper css rules to meet our desired transition. Rules should include slide
in it and transtion durations should be compatible with timeout
prop of CSSTransition
.
/* ANIMATIONS */
.slide-enter {
transform: translateX(100%);
}.slide-enter-active {
transform: translateX(0%);
transition: transform 1000ms ease-in-out;
}.slide-exit {
transform: translateX(0%);
}.slide-exit-active {
transform: translateX(-100%);
transition: transform 1000ms ease-in-out;
}
The demo display is below with routing and navigation. Each route has a different background and changing route cause background transition: https://codesandbox.io/embed/pk81k02xjm?fontsize=14&hidenavigation=1&theme=dark
PS: I don’t know why but inside the sandbox transitions don’t look as intended so you can check on https://pk81k02xjm.csb.app/
Author: Özgün Bal