Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Enter and leave animations: Transition

When v-if removes an element, it disappears instantly. The built-in Transition component adds CSS classes to the element at the moments it appears and disappears, and you describe the animation in those classes. Nothing needs installing — the component ships with Vue.

The Transition component

Wrap an element with v-if or v-show in Transition:

<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
 
const showHelp = ref(false)
</script>
 
<template>
  <button @click="showHelp = !showHelp">Help</button>
  <Transition name="fade">
    <p v-if="showHelp">Type the task and press Enter.</p>
  </Transition>
</template>
 
<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}
 
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>

Now the hint fades in and out over 0.3 seconds. The name="fade" attribute sets the prefix of the class names.

Transition classes

ClassWhen it applies
fade-enter-fromThe first frame of entering — the starting state
fade-enter-activeThe whole entering phase — transition goes here
fade-enter-toThe final state of entering
fade-leave-fromThe first frame of leaving
fade-leave-activeThe whole leaving phase
fade-leave-toThe final state of leaving

The four classes from the example are usually enough: the "before" and "after" states match the element's normal look.

Animating a list

For v-for items use TransitionGroup. It works the same way, but for each list item:

<template>
  <TransitionGroup name="list" tag="ul">
    <li v-for="todo in todos" :key="todo.id">
      {{ todo.text }}
      <button @click="removeTodo(todo.id)">Delete</button>
    </li>
  </TransitionGroup>
</template>
 
<style scoped>
.list-enter-active,
.list-leave-active {
  transition: all 0.3s;
}
 
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
</style>

A new task slides in from the right, a deleted one slides right and fades. tag="ul" says which tag wraps the list — without it TransitionGroup renders no wrapper. The todos array and the removeTodo function come from the lists lesson.

Common mistake

Transition animates only a single element that appears or disappears. If there is no v-if or v-show inside, there is no animation: the element never enters or leaves. And in TransitionGroup every item needs a :key — without it Vue cannot tell a deleted task from its neighbour.

Thanks for reading!

Donate to the site — we work hard for you.