Slide Page CSS Transition on React with React Router

List Of Content

ADS Area (CARBON)

ADS Area (CARBON)

 

Getting Started

One of the awesome things you can add to your application, for example, your Portfolio as a developer and software engineer so you want to make it look absolutely stunning by adding smooth animations and uniquely different design alongside that making the transition between your pages with animation can grab a lot of intention to you and your app plus it will give the user a much better experience compared to a regular application.

 React Router uses a declarative page navigation which means that all the transition among your web pages are done on the client side, the server doesn't know or care about those navigations so in this case it can give you a lot of benefits adding to your apps for having a nice and elegant transition (Animation) when navigating between pages.

We will be using react-transition-group which allows you to add animations before and after a react element gets mounted or unmounted from the DOM it does handle all the logic of keeping track if the component behind the scenes all you have to do is to tell which component is going to be animated and what type of animation to be applied.

you can use regular react transition group animation or much better you can rely on a CSS Animation since you may already be familiar with plus it is super easy. We will be creating a CSS Page Slide Transition so one page slides on top of the other when navigating through pages.

So, first, install react-transition-group and install node-sass for using SASS with your react-create-app project.

npm install react-transition-group --save 

And node-sass 

npm install node-sass --save-dev 

We will not cover how to set up or use React router so I assume you already have a working application with a multipage setup with react-router-dom.

You can get the Full Working Source Code on Github.

Use React Transition Group 

We need to setup react transition group to work with react router so when it detects a location change (basically navigating to another page) it applies the specified animation.

Here is how my simple app looks like with react router only.

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }

  render() {
    const { location } = this.props;

    return (
      <div className="App">
        <Switch location={location}>
          <Route path="/" exact component={HomePage} />
          <Route path="/about" exact component={AboutPage} />
        </Switch>
      </div>
    );
  }
}

Basically, there are two pages the Home page and About page.

Let's wrap it up with React Transition Group component.

 render() {
    const { location } = this.props;
  /*Used to track if the page path did change so when can re-render the routes to apply animation */
    const currentKey = location.pathname.split("/")[1] || "/";
    //Specify the duration of the animation (on enter and on exit)
    const timeout = { enter: 800, exit: 400 };

    return (
      <TransitionGroup component="div" className="App">
        <CSSTransition
          key={currentKey}
          timeout={timeout}
          classNames="pageSlider"
          mountOnEnter={false}
          unmountOnExit={true}
        >
          <div>
            <Switch location={location}>
              <Route path="/" exact component={HomePage} />
              <Route path="/about" exact component={AboutPage} />
            </Switch>
          </div>
        </CSSTransition>
      </TransitionGroup>
    );
  }

The CSSTransition component will apply the specified CSS transition class through className prop plus it also takes a timeout object to know the duration of the transition on entering and on exit.

CurrentKey is used to keep track if the current page path has been changed so we can re-render the CSStransition group through the React key prop which it detects if the key value changes it re-renders current component and of course that will allow us to apply the transition animation whenever we navigate to a different page on the routes list.

Although, this is a slide animation but it is not smart enough to know either to apply transition from left to right or vice versa from right to left which is linked to the current page, for example if you're at the Home Page and you navigated to about page the page should apply transition from right to left since the Home page in this case is concerned as a base 0 path, in the other hand if you suddenly decided to move back to home page then you should expect the transition direction to be from left to right to make it feel a bit smarter other than always applying the same animation direction for whatever page path throughout your app.

So let's add a method for calculating the current page depth, depth is the number of paths exists in a URL so, for example, the root path "/" has a depth of 0 since there is an empty path, where for the "/about" page route it has a depth of 1.

getPathDepth(location) {
  let pathArr = location.pathname.split("/");
  pathArr = pathArr.filter(n => n !== "");
  return pathArr.length;
}

We want to have a prevDepth and then compare it with current depth to decide the transition's direction.

constructor(props) {
  super(props);
  this.state = {
    //Get initial depth of current page 
    prevDepth: this.getPathDepth(this.props.location)
  };
}

componentWillReceiveProps() {
  //When props are updated, update the current path 
  //props supplies us with the location object which has a router location info
  this.setState({ prevDepth: this.getPathDepth(this.props.location) });
}

CSS Slide Transition

Let's add the CSS Transition which is going to be responsible for animating and applying the smooth slide animation between pages.

You can create a new folder name it pageTransitions and put all of your transitions in there, create a new slideTransition.scss file (you can use regular CSS) but it is easier and faster to do it with SASS.

/* slideTransition.scss */

//old page exiting, hides it underneath (bottom) 
.pageSlider-exit > .page {
  z-index: 1;
}
//new page entering, show it on top
.pageSlider-enter > .page {
  z-index: 10;
}
//LEFT transition transform 100% to the right
.pageSlider-enter.left > .page {
  transform: translate3d(100%, 0, 0);
}
//RIGHT transition transform -100% to the left
.pageSlider-enter.right > .page {
  transform: translate3d(-100%, 0, 0);
}
//old exit left direction
.pageSlider-exit.left > .page {
  transform: translate3d(-100%, 0, 0);
}
//old exit right direction 
.pageSlider-exit.right > .page {
  transform: translate3d(100%, 0, 0);
}
//Enter is active (Page has finished transitioning) make it settle down 
.pageSlider-enter.pageSlider-enter-active > .page {
  transform: translate3d(0, 0, 0);
  //Apply all transitions 
  transition: all 800ms ease-in-out;
}

Regarding this pattern the CSSTransition works and read your CSS supplied transition class, you can easily create your own custom transitions and animation like fading or dissolve.

If you can notice we're adding a .page class to get the CSS code to be applied on, so now for every page we want to apply the animation to we need to add .page class to its classNames list.

Make it Smarter

On real time we need to decide either to move from left to right or from right to left by comparing the previous page depth which is in the state with the current depth.

<div
  className={
    this.getPathDepth(location) - this.state.prevDepth >= 0
      ? "left"
      : "right"
  }
>
  <Switch location={location}>
    <Route path="/" exact component={HomePage} />
    <Route path="/about" exact component={AboutPage} />
  </Switch>
</div>

So we compare both depths and decide to use left if current depth is greater than the previous one which means we are not in the home page so we will be applying transition from left to right otherwise apply from right to left.

The left and right classes are the defined classes names in the page slider transition class.

Finally, add the page className to the pages you which to apply the transition to when navigating to or from other pages.


export default class HomePage extends React.Component {
  render() {
    return (
      <div className="page-container page">
         Page Content 
      </div>
   );
  }
}

Try to run your application and navigate about pages you should see a really smooth and nice sliding left/right animation between your pages. 

 

Share Tutorial

Made With By

Ipenywis Founder, Game/Web Developer, Love Play Games