Table of contents [Show]
- Introduction to Vue.js Transitions
- Step 1: The Basics of the <transition> Component
- Step 2: Transition Classes Explained
- Step 3: Using CSS Animations Instead of Transitions
- Step 4: Transitioning Between Multiple Elements
- Step 5: Using <transition-group> for Lists
- Step 6: JavaScript Hooks for Advanced Animations
- Step 7: Full Practical Example — Animated Modal Component
- Best Practices for Vue.js Animations
- Conclusion
Introduction to Vue.js Transitions
Animations make the difference between an app that feels stiff and one that feels alive. Vue.js makes adding animations and transitions painless with its built-in <transition> and <transition-group> components.
Whenever an element enters or leaves the DOM, Vue lets you apply CSS or JavaScript animations without heavy boilerplate. Whether it’s fading in a modal, sliding a sidebar, or animating list reordering, Vue’s transition system is your new best friend.
Step 1: The Basics of the <transition> Component
The simplest way to animate in Vue is by wrapping an element with the <transition> component. Vue automatically detects when the element enters or leaves the DOM and applies CSS classes for you.
Example: Fading Text
<template>
<div>
<button @click="show = !show">Toggle</button>
<transition name="fade">
<p v-if="show">Hello Vue Animations!</p>
</transition>
</div>
</template>
<script setup>
import { ref } from "vue";
const show = ref(true);
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
Here’s what happens:
.fade-enter-fromsets the starting style when the element enters..fade-enter-activedefines the transition duration and easing..fade-leave-toapplies when the element leaves.
Step 2: Transition Classes Explained
Vue adds and removes special classes during the transition lifecycle:
Default Transition Classes
<transition name="fade">
<!-- Vue automatically applies these classes -->
</transition>
Classes applied:
- fade-enter-from: Initial state before entering.
- fade-enter-active: Transition properties while entering.
- fade-enter-to: Final state after enter starts.
- fade-leave-from: Initial state before leaving.
- fade-leave-active: Transition properties while leaving.
- fade-leave-to: Final state after leave starts.
Step 3: Using CSS Animations Instead of Transitions
Instead of transitions, you can use @keyframes animations. Vue will detect them the same way.
Example: Bouncing Text
<style>
.bounce-enter-active {
animation: bounce-in 0.6s;
}
.bounce-leave-active {
animation: bounce-out 0.6s forwards;
}
@keyframes bounce-in {
0% { transform: scale(0.8); opacity: 0; }
50% { transform: scale(1.1); opacity: 1; }
100% { transform: scale(1); }
}
@keyframes bounce-out {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(0.8); opacity: 0; }
}
</style>
This creates a fun “bounce” effect on entry and a smooth shrink on exit.
Step 4: Transitioning Between Multiple Elements
Vue allows you to transition between two different elements or components by using the mode attribute.
Example: Switching Between Login and Register
<transition name="fade" mode="out-in">
<component :is="view"></component>
</transition>
<script setup>
import { ref } from "vue";
const view = ref("login-form");
</script>
The mode="out-in" ensures the leaving element finishes before the new one enters.
Step 5: Using <transition-group> for Lists
The <transition-group> component animates lists when items are added, removed, or reordered.
Example: Animated To-Do List
<template>
<div>
<input v-model="newItem" placeholder="Add item" />
<button @click="addItem">Add</button>
<transition-group name="list" tag="ul">
<li v-for="(item, index) in items" :key="item">
{{ item }}
<button @click="removeItem(index)">X</button>
</li>
</transition-group>
</div>
</template>
<script setup>
import { ref } from "vue";
const items = ref(["Learn Vue", "Build UI"]);
const newItem = ref("");
const addItem = () => {
if (newItem.value) {
items.value.push(newItem.value);
newItem.value = "";
}
};
const removeItem = (index) => {
items.value.splice(index, 1);
};
</script>
<style>
.list-enter-active, .list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from {
opacity: 0;
transform: translateY(20px);
}
.list-leave-to {
opacity: 0;
transform: translateY(-20px);
}
</style>
When items are added or removed, they smoothly fade and slide in or out.
Step 6: JavaScript Hooks for Advanced Animations
Sometimes CSS alone isn’t enough. Vue lets you hook into transition lifecycle methods to animate with JavaScript or external libraries like GSAP.
Example: Using JavaScript Hooks
<transition
@before-enter="beforeEnter"
@enter="enter"
@leave="leave">
<div v-if="show">Animate me!</div>
</transition>
<script setup>
import { ref } from "vue";
const show = ref(true);
const beforeEnter = (el) => {
el.style.opacity = 0;
};
const enter = (el, done) => {
setTimeout(() => {
el.style.transition = "opacity 1s";
el.style.opacity = 1;
done();
}, 100);
};
const leave = (el, done) => {
el.style.transition = "opacity 1s";
el.style.opacity = 0;
setTimeout(done, 1000);
};
</script>
Here we control every part of the animation lifecycle with JavaScript.
Step 7: Full Practical Example — Animated Modal Component
Let’s put it all together by creating a reusable animated modal component with transitions.
<!-- Modal.vue -->
<template>
<transition name="modal-fade">
<div v-if="show">
<div >
<slot></slot>
<button @click="$emit('close')">Close</button>
</div>
</div>
</transition>
</template>
<script setup>
defineProps({
show: Boolean
});
</script>
<style scoped>
.modal-fade-enter-active, .modal-fade-leave-active {
transition: opacity 0.5s;
}
.modal-fade-enter-from, .modal-fade-leave-to {
opacity: 0;
}
.modal-overlay {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.6);
display: flex;
align-items: center;
justify-content: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
}
</style>
Using the Modal
<template>
<div>
<button @click="showModal = true">Open Modal</button>
<Modal :show="showModal" @close="showModal = false">
<h2>Hello Modal</h2>
<p>This modal uses Vue transitions!</p>
</Modal>
</div>
</template>
<script setup>
import { ref } from "vue";
import Modal from "./Modal.vue";
const showModal = ref(false);
</script>
This modal fades in and out smoothly, making the UI feel professional and polished.
Best Practices for Vue.js Animations
- Keep it subtle: Overly flashy animations can annoy users.
- Use reusable components: Wrap animations into reusable UI components like modals or dropdowns.
- Optimize performance: Use CSS transitions where possible; only fall back to JavaScript for complex cases.
- Test on devices: Animations may feel different on desktop vs mobile.
Conclusion
Vue.js makes transitions and animations elegant and approachable. Whether you’re adding a subtle fade, animating list items, or building full-screen modals, Vue gives you the tools to make your interfaces feel alive. By practicing with <transition>, <transition-group>, and hooks, you’ll be able to craft smooth, delightful experiences that users love.
Now it’s your turn—go build something beautiful and animated in Vue!






