Animate entrances, exits, and list changes with the Transition and TransitionGroup components built into Vue — no library needed.
Why: wrap an element in <Transition> and Vue adds CSS classes while it enters and leaves — your stylesheet decides what those classes do. Built into Vue; nothing to install. When: entrances, exits, and toggles; reach for a library only for complex orchestrated sequences.
<script setup lang="ts">
import { ref } from 'vue'
const visible = ref(true)
</script>
<template>
<button @click="visible = !visible">Toggle</button>
<!-- Vue applies fade-enter-* and fade-leave-* classes automatically -->
<Transition name="fade">
<p v-if="visible">Saved successfully</p>
</Transition>
</template>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: all 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(-16px);
}
</style>Why: <TransitionGroup> is <Transition> for lists — new items animate in, removed items animate out, and the .name-move class makes the OTHER items slide smoothly out of the way instead of jumping.
<script setup lang="ts">
import { ref } from 'vue'
const items = ref([1, 2, 3])
let nextId = 4
</script>
<template>
<button @click="items.unshift(nextId++)">Add to top</button>
<!-- Like Transition, but for v-for lists — items need a :key -->
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item">Item {{ item }}</li>
</TransitionGroup>
</template>
<style scoped>
.list-enter-active,
.list-move {
transition: all 0.3s ease;
}
.list-enter-from {
opacity: 0;
transform: translateY(-8px);
}
</style>