Transitions and Animations

Transitions and animations play a big part in adding polish to any web application. Fortunately, Vue offers several different ways to add transitions and animations.

Class binding

Transitions and animations can occur by using class bindings. However, an animation class only can be applied to an element that has already been rendered. If the animation class is placed on an element that is being rendered simultaneously, no animation will occur.

const app = Vue.createApp({
  data: function () {
    return {
      spin: false
    }
  }
})

const vm = app.mount('#app')
<div id="app" class="app"> 
  <div class="box" :class="{spin: spin}"></div>
  <button @click="spin = true">Spin</button>
</div>
.spin {
  transform: rotate(360deg);
  transition: 1s;
}

Transition component

A more effective way of applying transitions and animations is to use the transition component. The transition component allows you to add entering/leaving transition to any element or component that is conditionally rendered using v-if or v-show.

const app = Vue.createApp({
   data() {
    return {
      show: true
    }
  }
})

const vm = app.mount('#app')
<div id="app">
  <button @click="show = !show">
    Toggle
  </button>

  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>
</div>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

The transition component can also be used with existing animation libraries. Instead of using the class names generated by Vue, custom class names can be provided instead.

The following example uses the Animate.css library.

const app = Vue.createApp({
   data() {
    return {
      show: true
    }
  }
})

const vm = app.mount('#app')
<div id="app" class="app">
  <button @click="show = !show">
    Toggle
  </button>
  
  <transition 
     enter-active-class="animate__animated animate__bounceIn"
     leave-active-class="animate__animated animate__bounceOut">
    <p v-if="show">hello</p>
  </transition>
</div>

Transition Group

While the transition component is meant for a single element, the transition-group component can be used for a list of items rendered using the v-for directive.

const app = Vue.createApp({
  data: function () {
    return {
      items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
      nextNum: 10
    }
  },
  methods: {
    randomIndex: function () {
      return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
      this.items.splice(this.randomIndex(), 0, this.nextNum++)
    },
    remove: function () {
      this.items.splice(this.randomIndex(), 1)
    }
  }
})

const vm = app.mount('#app')
<div id="app">
  <button @click="add">Add</button>
  <button @click="remove">Remove</button>
  <transition-group name="list" tag="p">
    <span v-for="item in items" :key="item" class="list-item">
      {{ item }}
    </span>
  </transition-group>
</div>
.list-enter-active,
.list-leave-active {
  transition: all 1s ease;
}

.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}