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
| Class | When it applies |
|---|---|
fade-enter-from | The first frame of entering — the starting state |
fade-enter-active | The whole entering phase — transition goes here |
fade-enter-to | The final state of entering |
fade-leave-from | The first frame of leaving |
fade-leave-active | The whole leaving phase |
fade-leave-to | The 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.