Animating between routes with route transitions in Vue

Animating between routes with route transitions in Vue


Working on a Vue.js application, there’s a high chance that components or items are going to be inserted, updated from the DOM. It’s always good practice to ease that process to obtain a great user experience.

In this article, I’ll be giving a brief overview of the difference in making a Vue application smooth by applying Vue transitions to routes.

Here’s how Route transitions look in our app:

Applying animations to your routes

The type of animations you want to apply to routes my differ for each route or you use a global animation for all routes.

To animate components in Vue, we use the wrapper component; transition.

So the root element in the component to be rendered will be wrapped with the transition component if you want per-route transitions or wrapping router-view in the base component with transition if you want a global dynamic transition.

Aside from wrapping the templates in a transition component, we also specify the name of the animation which we will use in CSS to create the animations.

Transition classes

There are six classes that represent the different states in an animation. They are the enter/leave transition classes.

  1. v-enter
  2. v-enter-active
  3. v-enter-to
  4. v-leave
  5. v-leave-active
  6. v-leave-to

These six classes in that order are responsible for the flow of the animations, to learn more about what each of them is, check out the official doc.

You’ll notice the v- prefix, we use that if the animation’s name was not specified for the transition wrapper. It’s also possible to specify a custom class to apply for a certain transition state:

<transition enter-active-class="custom-class-here">
  <h1>Hello there</h1>
</transition>

This way, we can use custom animation libraries like Animate.css etc.

Per-Route Vue Transitions

Take this single file component for example:

<template>
<transition name="fade">
  <h3> Login </h3>
</transition>
</template>

<script>
export default {
  name: 'login',
  data(){
    return {}
  }
}
</script>

<style scoped>
/*transition the opacity when the element enters and leaves the DOM*/
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s; 
}

/*set opacity to 0 at element's entrance and exit*/
.fade-enter, .fade-leave-to {
  opacity: 0; 
}
</style>

With this method, we can have different animations for separate routes.

Global dynamic Vue transitions

And if we wanted to have unified route transitions based on the route, we can do achieve this by watching the $route object. Determining the path being navigated to will help us bind the correct name to the transition wrapper.

<template>
<nav>
  <h2>Title</h2>
</nav>

<transition :name="animationName" >
  <router-view class="child-view" />
</transition>
</template>

<script>
export default {
 data(){
  return{
    animationName = undefined
  }
 }
 watch: {
  '$route'(to, from){
    const to_depth = to.path.split('/').length
    const to_depth = from.path.split('/').length
    this.animationName = to_depth < from_depth ? 'slide-right' : 'slide-left'
  }
 }
}
</script>

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}
.fade-enter,
.fade-leave-active {
  opacity: 0;
}
.child-view {
  position: absolute;
  width: 100%;
  left: 0;
  transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}
.slide-left-enter,
.slide-right-leave-active {
  opacity: 0;
  -webkit-transform: translate(30px, 0);
  transform: translate(30px, 0);
}
.slide-left-leave-active,
.slide-right-enter {
  opacity: 0;
  -webkit-transform: translate(-30px, 0);
  transform: translate(-30px, 0);
}
</style>

The elements to be rendered in router-view had to be given am absolute position so they don’t appear to glitch during animations.

I built an app using this Global dynamic route method a while back, you can check it out here

And the source code for the app


Share on social media

//