Paulund

VueJS - Transition Effects

VueJS provides an inbuilt way of providing transitions when making changes to the DOM, these can be applied when inserting items, updating items or deleting items from the DOM.

Transition Classes

The way VueJS adds transitions to the application is by using CSS transitions to provide animations to your application. It does this by automatically adding CSS classes to the wrapper of element. There are 4 classes that Vue will add before the entering component and leaving component. - v-enter - Added when inserting the element

  • v-enter-active - Active and ending state for inserting the element, CSS class is removed when animation finishes.
  • v-leave - The starting class for the leave transition
  • v-leave-active - Added when the leave transition is set, removed when the animation finishes.

To add a transition in Vue you can do this by adding a transition tag to wrap an element.

<div id="transition-example">
  <button @click="show = !show">
    Display Element
  </button>
  <transition name="fade">
    <p v-if="show">I'm fading</p>
  </transition>
</div>

In the above example we wrap a transition tag around a paragragh tag with a v-if directive. When the show data property is true it will display the paragraph tag. Because we've added a transition tag around paragraph tag with a name of fade we will now have new transition CSS classes for fade. Fade is the CSS class name used to prefix the transition classes. First the name of the transition fade then the name of the transition event.

  • .fade-enter
  • .fade-enter-active
  • .fade-leave
  • .fade-leave-active

To create a fade In/Out transition you'll need to add the following CSS classes.

.fade-enter-active, .fade-leave-active {
  transition: opacity .5s
}
.fade-enter, .fade-leave-active {
  opacity: 0
}

You can also do something similar for sliding effects using the same HTML but changing the name in the transition tag to slide.

<div id="transition-example">
  <button @click="show = !show">
    Display Element
  </button>
  <transition name="slide">
    <p v-if="show">I'm sliding</p>
  </transition>
</div>

Vue will now add CSS classes of - .slide-enter

  • .slide-enter-active
  • .slide-leave
  • .slide-leave-active

To make an element slide in we just need to start it off the page and transition it into the page.

.slide-enter-active, .slide-leave-active {
    transition: transform .5s;
    transform: translate3d(0, 0, 0);
}
.slide-enter, .slide-leave-active {
    transform: translate3d(-100%, 0, 0);
    visibility: visible;
}

CSS Animation

Instead of using CSS transitions to add effects to your application you can use CSS animations to perform the effects. When using an animation function you don't need to use the -enter class and can just use -enter-active. In this example let's use one of the animations from the Github Repo animate.css bounceInUp.css, then to exit we'll use the bounceOutDown.css.

@keyframes bounceInUp {
  from, 60%, 75%, 90%, to {
    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
  }

  from {
    opacity: 0;
    transform: translate3d(0, 3000px, 0);
  }

  60% {
    opacity: 1;
    transform: translate3d(0, -20px, 0);
  }

  75% {
    transform: translate3d(0, 10px, 0);
  }

  90% {
    transform: translate3d(0, -5px, 0);
  }

  to {
    transform: translate3d(0, 0, 0);
  }
}

@keyframes bounceOutDown {
  20% {
    transform: translate3d(0, 10px, 0);
  }

  40%, 45% {
    opacity: 1;
    transform: translate3d(0, -20px, 0);
  }

  to {
    opacity: 0;
    transform: translate3d(0, 2000px, 0);
  }
}

Now we can add the Vue CSS classes.


.bounce-enter-active {
  animation: bounceInUp .5s;
}
.bounce-leave-active {
  animation: bounceOutDown .5s;
}

CSS Custom Transition Classes

Another option you have is to define your own CSS classes which are used on the 4 transition classes, you do this by adding the transition classes as attributes to the transition tag.


<transition
    name="transition-custom-classes"
    enter-active-class="custom-enter-class"
    leave-active-class="custom-leave-class"
>
    <p v-if="show">hello</p>
</transition>

Now instead of using the CSS classes .enter-active-class and .leave-active-class we can use .custom-enter-class and .custom-leave-class. This means we can now easily add the classes from animate.css into the transition tag instead of duplicating the CSS into our own application.


<transition
    name="transition-custom-classes"
    enter-active-class="animated bounceInUp"
    leave-active-class="animated bounceOutDown"
>
    <p v-if="show">hello</p>
</transition>

Route Transitions

In a previous series we looked into how to use the Vue Router library using the tag.


<transition
    name="route-transition"
    enter-active-class="animated bounceInUp"
    leave-active-class="animated bounceOutDown"
>
    <router-view></router-view>
</transition>

You can wrap this tag in a transitions tag which will add transitions to the components inserted into the router-view, we're now able to add animation effects when moving between different components.

Dynamic Transition Effects

We can even add the functionality to have dynamic transition effects by binding to the name attribute of the transition tag.


<transition :name="transitionName">
  <router-view></router-view>
</transition>

transitionName can now be a data point in your app which can be changed on the watch of the $route changes.


watch: {
  '$route' (to, from) {
    this.transitionName = 'bounceIn'
  }
}

In the above example we're hard coding the transitionName to bounceIn on changes to the route, we can replace this with another data point like a textbox or select box and use this value instead. Let's build a small page that has a dropdown with all the animations from animate.css and allow the user to choose this animation and we'll use the selected animation for changing page routes.


<div id="app">
    <h1>Dynamic Route Transition Effects</h1>
    <p>
        <router-link to="/">Home</router-link>
        <router-link to="/about">About</router-link>
        <router-link to="/portfolio">Portfolio</router-link>
        <router-link to="/blog">Blog</router-link>
        <router-link to="/contact">Contact</router-link>
    </p>
    <p>
    <label for="">In Animation</label><select class="input" v-model="selectedAnimationIn"></select>
    <label for="">Out Animation</label><select class="input" v-model="selectedAnimationOut"></select>
    </p>

    <transition
            name="route-transition"
            v-on:enter="enter",
            v-on:leave="leave"
    >
        <router-view></router-view>
    </transition>
</div>

To start with we have the router links to define the different pages in the page. Then we have a select element which has a v-model directive for selectedAnimationIn a data point for storing the selected option, then another select for the selectedAnimationOut. Finally we have a transition tag, like before we add a name to the transition, but this time we're changing the enter and leave CSS classes to use JavaScript event by using the v-on directive. Now on the enter event of the transition we're calling the enter method in our app, and for the leave event we're calling the leave method. Within these methods we need to grab the selected values from the select boxes and add these to the elements class list.

const app = new Vue({ router,

    data: {
        selectedAnimationIn: '',
        selectedAnimationOut: ''
    },

    methods: {
        enter: function(el)
        {
            el.classList.add('animated');
            el.classList.add(this.selectedAnimationIn);
        },
        leave: function(el)
        {
            el.classList.add('animated');
            el.classList.add(this.selectedAnimationOut);
        }
    }
}).$mount('#app');

Now when we navigate to the app and select our In animation and Out animation then change the route we'll see these animations used.