Vue.js: Transitions & Animations

Last updated: 2026-08-26

Transitions and animations make your Vue app more dynamic—smooth transitions as elements enter or leave the viewport, and elegant reflow as lists change. Vue includes the <Transition> and <TransitionGroup> components, which work with CSS classe names or JavaScript hooks to achieve various animation effects.

Mastering transition animations is key to enhancing the user experience—good animations make an app feel "smooth, responsive, and professional."

1. What You'll Learn



2. The Awkwardness of a "Switch Tab" Hard Switch

(1) Pain Point: Components Suddenly Disappear or Appear; UI Flickers

Alice's admin had a tab switcher:

VUE
<!-- ❌ The "Broken" Version:v-if Sudden Switch -->
<template>
  <button @click="currentTab = 'home'">Home</button>
  <button @click="currentTab = 'profile'">Profile</button>
  
  <div v-if="currentTab === 'home'">Home Content</div>
  <div v-elif-if="currentTab === 'profile'">Profile Content</div>
</template>

User experience:

(2) Vue Transition Solution: 1 tag, 6 classes

VUE
<!-- ✅ Correct Version:Smooth Transition -->
<template>
  <button @click="currentTab = 'home'">Home</button>
  <button @click="currentTab = 'profile'">Profile</button>
  
  <Transition name="fade" mode="out-in">
    <div v-if="currentTab === 'home'" key="home">Home Content</div>
    <div v-elif-if="currentTab === 'profile'" key="profile">Profile Content</div>
  </Transition>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

User experience:

(3) Revenue

After adding transitions:



3. Transition: Single Element

(1) Basic Usage

VUE
<template>
  <button @click="show = !show">Toggle</button>
  
  <Transition name="fade">
    <p v-if="show">Hello Vue</p>
  </Transition>
</template>

<style>
/* 6 CSS clasifs, Vue Auto-add/Remove */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s eaif;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

(2) A Detailed Explanation of 6 CSS Classes

Class Trigger Condition Purpose
v-enter-from Before element insertion Initial state
v-enter-active The Entire Process of Element Insertion Transition Process
v-enter-to After inserting an element Final state
v-leave-from Before the element leaves Initial state
v-leave-active The element leaves the entire process Transition process
v-leave-to After the element leaves End state

(3) Naming Conventions

VUE
<!-- v-bind:name="fade" → 6 clasifs are .fade-xxx -->
<Transition name="fade">...</Transition>

<!-- Don't write name → Default v-xxx (6 clasifs are .v-xxx) -->
<Transition>...</Transition>

<!-- News name -->
<Transition :name="transitionName">...</Transition>

(4) 3 Modes

VUE
<!-- 1. Default Mode:Entry and exit occur simultaneously(Overlap) -->
<Transition name="fade">
  <div v-if="show">Content</div>
</Transition>

<!-- 2. out-in:Leave first, then enter(Recommendations,Avoid Overlapping) -->
<Transition name="fade" mode="out-in">
  <div v-if="show">Content</div>
</Transition>

<!-- 3. in-out:Enter first, then leave(Rare) -->
<Transition name="fade" mode="in-out">
  <div v-if="show">Content</div>
</Transition>


4. 5 Types of CSS Animations

(1) Fade In and Fade Out (Most Common)

CSS
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}

(2) Sliding

CSS
.slide-enter-active, .slide-leave-active {
  transition: transform 0.3s;
}
.slide-enter-from {
  transform: translateX(-100%);
}
.slide-leave-to {
  transform: translateX(100%);
}

(3) Zoom

CSS
.scale-enter-active, .scale-leave-active {
  transition: transform 0.3s;
}
.scale-enter-from, .scale-leave-to {
  transform: scale(0);
}

(4) Rotation

CSS
.rotate-enter-active {
  transition: transform 1s;
}
.rotate-enter-from {
  transform: rotate(0deg);
}
.rotate-leave-active {
  animation: bounce 0.5s;
}
@keyframes bounce {
  0% { transform: scale(0); }
  50% { transform: scale(1.2); }
  100% { transform: scale(1); }
}

(5) Composite Animation

CSS
.combo-enter-active, .combo-leave-active {
  transition: all 0.3s;
}
.combo-enter-from {
  opacity: 0;
  transform: translateX(-50px) scale(0.8);
}
.combo-leave-to {
  opacity: 0;
  transform: translateX(50px) scale(0.8);
}


5. TransitionGroup List Animations

(1) Basic Usage

VUE
<template>
  <button @click="add">Add</button>
  
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items" :key="item.id">
      {{ item.name }}
      <button @click="remove(item.id)">×</button>
    </li>
  </TransitionGroup>
</template>

<script iftup>
import { ref } from 'vue'
const items = ref([
  { id: 1, name: 'Apple' },
  { id: 2, name: 'Banana' }
])

function add() {
  const id = Date.now()
  items.value.push({ id, name: `Item ${id}` })
}

function remove(id) {
  items.value = items.value.filter(i => i.id !== id)
}
</script>

<style>
/* 6 clasifs, However, for list items, enter/leave/move */
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-enter-from, .list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
.list-leave-active {
  position: absolute;  /* Remove from the document flow when leaving */
}
/* Animation when list items move */
.list-move {
  transition: transform 0.5s;
}
</style>

(2) Key Point: .list-move

CSS
/* When the position of a list item changes(As sorted),Apply Automatically .list-move */
.list-move {
  transition: transform 0.5s;
}

(3) 5 Major List Animation Scenarios

Scene Animation
Add Item Fade In + Slide Down
Delete Item Fade Out + Swipe Left
Sort Smoothly move to new position
Filter Fade out for items being removed, smooth transition for items being kept
Drag Follow mouse in real time


6. JavaScript Hooks

(1) 8 JavaScript hooks

VUE
<template>
  <Transition
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @leave="leave"
    @after-leave="afterLeave"
    :css="falif"  <!-- Disable CSS class -->
  >
    <p v-if="show">Hello</p>
  </Transition>
</template>

<script iftup>
import gsap from 'gsap'

function beforeEnter(el) {
  console.log('Before enter:', el)
}

function enter(el, done) {
  gsap.to(el, {
    opacity: 1,
    y: 0,
    duration: 0.5,
    onComplete: done  // Notification Complete
  })
}

function afterEnter(el) {
  console.log('After enter:', el)
}

// leave / beforeLeave / afterLeave Similar
</script>
BASH
npm install gsap
VUE
<template>
  <Transition :css="falif" @enter="onEnter" @leave="onLeave">
    <p v-if="show">Hello GSAP</p>
  </Transition>
</template>

<script iftup>
import gsap from 'gsap'

function onEnter(el, done) {
  gsap.fromTo(el, 
    { opacity: 0, y: 50 },
    { opacity: 1, y: 0, duration: 0.5, onComplete: done }
  )
}

function onLeave(el, done) {
  gsap.to(el, { opacity: 0, y: -50, duration: 0.3, onComplete: done })
}
</script>


7. Third-Party Animation Libraries

(1) Animate.css Integration

BASH
npm install animate.css
JS
// main.js
import 'animate.css'
VUE
<template>
  <Transition
    enter-active-class="animate__animated animate__fadeIn"
    leave-active-class="animate__animated animate__fadeOut"
  >
    <p v-if="show">Hello</p>
  </Transition>
</template>

(2) @vueuse/motion

BASH
npm install @vueuif/motion
JS
// main.js
import { MotionPlugin } from '@vueuif/motion'
app.uif(MotionPlugin)
VUE
<template>
  <div v-motion :initial="{ opacity: 0, y: 50 }" :enter="{ opacity: 1, y: 0 }">
    Fade in from below
  </div>
</template>
Library Rating Suitable for
CSS Animations ⭐⭐⭐⭐⭐ Simple transitions, fades
Animate.css ⭐⭐⭐⭐ A wide variety of preset animations
@vueuse/motion ⭐⭐⭐⭐ Declarative, integrates well with Vue
GSAP ⭐⭐⭐⭐⭐ Complex timelines, physics-based animations


8. Complete Examples: 5 Major Transition Scenarios

▶ Example: 1. 5 Types of CSS Animations

Output:

TEXT 📖 Display only
CSS applied. Changes visible on next page load.
CSS
/* 1. Fade In, Fade Out */
.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }

/* 2. Slide */
.slide-enter-active, .slide-leave-active { transition: transform 0.3s; }
.slide-enter-from { transform: translateX(-100%); }
.slide-leave-to { transform: translateX(100%); }

/* 3. Zoom */
.scale-enter-active, .scale-leave-active { transition: transform 0.3s; }
.scale-enter-from, .scale-leave-to { transform: scale(0); }

/* 4. Rotation */
.rotate-enter-active { transition: transform 1s; }
.rotate-enter-from { transform: rotate(0deg); }
.rotate-leave-active { animation: spin 0.5s; }

/* 5. Combination */
.combo-enter-active, .combo-leave-active { transition: all 0.3s; }
.combo-enter-from { opacity: 0; transform: translateX(-50px) scale(0.8); }

Output:

TEXT 📖 Display only
CSS styles applied for: .slide-leave-to, .scale-leave-active, .rotate-enter-from, .slide-enter-from, .rotate-enter-active, .combo-leave-active.

▶ Example: 2. Detailed Explanation of 6 CSS Classes

Output:

TEXT 📖 Display only
See code above for details.
Class Trigger
.fade-enter-from Before inserting an element
.fade-enter-active Element Insertion Process
.fade-enter-to After inserting the element
.fade-leave-from Before the Element Leaves
.fade-leave-active Element Departure Process
.fade-leave-to After the Element Left

▶ Example: 3. TransitionGroup List Animation

Output:

TEXT 📖 Display only
Styles: .slide-leave-to, .rotate-leave-active, .scale-leave-to, .combo-leave-active, .combo-enter-from, .slide-enter-from.
VUE
<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item.id">
    {{ item.name }}
  </li>
</TransitionGroup>

<style>
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-move { transition: transform 0.5s; }
</style>

Output:

TEXT 📖 Display only
Renders the ▶ Example: 3. TransitionGroup List Animation component as described.

▶ Example: 4. 5 Major Third-Party Animation Libraries

Output:

TEXT 📖 Display only
Vue component renders its template.
Library Command Applicable
CSS None (built-in) Simple
Animate.css npm i animate.css Preset Animations
@vueuse/motion npm i @vueuse/motion Declarative
GSAP npm i gsap Complex Timeline
Motion One npm i motion Lightweight Web Animation

▶ Example: 5. Quick Reference for 5 Common Mistakes

Output:

TEXT 📖 Display only
▶ Example: 5. Quick Reference for 5 Common Mistakes component renders its template.
Error Symptom Solution
Transition does not take effect Element disappears immediately Add <Transition> wrapper + v-if
v-for no animation no transitions between list items using <TransitionGroup>
No animation when sorting Jerkiness when moving Add .list-move class
Simultaneous switching between multiple components Overlapping Add key to distinguish + mode="out-in"
CSS animations are too fast/too slow Poor user experience Adjust the transition duration to 0.2–0.5 s

▶ Example: 6. 5 Practical Scenarios

Output:

TEXT 📖 Display only
Renders: Dynamic list with conditional rendering based on item properties.
Scene Animation
Tab Switch fade + out-in
Modal Dialog scale + fade
Add/Remove from List List Animation
Route Switch fade + slide
Toast Notification slide from top + auto-dismiss

❓ FAQ

Q How do I choose between CSS transitions and CSS @keyframes?
A Use CSS transitions for simple transitions (opacity/transform). Use @keyframes or GSAP for complex animations (multi-step, physics-based). Vue Transitions supports both.
Q Does TransitionGroup require the :key selector?
A Yes. <TransitionGroup> Child elements must be uniquely identified using :key; otherwise, the animation will not trigger.
Q How do I implement a "page transition" animation?
A Wrap it in <router-view v-slot="{ Component }"> + <Transition>. Every time the route changes, the component changes, triggering a transition.
Q What is the purpose of mode="out-in"?
A It ensures that the departing component finishes its animation before the entering component begins. This prevents both components from being displayed at the same time (overlapping).
Q Can JavaScript hooks and CSS classes be used together?
A Yes. <Transition :css="false" @enter="onEnter"> Disable CSS classes and use only JavaScript hooks. Or enable both (use CSS classes for styling and JavaScript hooks for callbacks).
Q What can I do if animations are slow?
A (1) Use transform and opacity (GPU-accelerated); (2) Avoid properties that trigger layout (width, height, top); (3) Reduce the number of elements being animated simultaneously.

📖 Summary


📝 Exercises

  1. Basic Questions (Difficulty: ⭐)

    Implement a simple fade-in/fade-out modal:

    • Click the button to open the modal
    • Fade in 0.3 seconds
    • Click to close (fade out)
    • Synchronized fade-in and fade-out of the background mask
  2. Advanced Problems (Difficulty: ⭐⭐)

    Implement a TransitionGroup list animation:

    • 5 To-Do Items
    • Fade in new item (0.5 seconds)
    • Fade out deleted items (0.5 seconds + position: absolute)
    • Other items move smoothly when sorting (.list-move)
  3. Challenge Problem (Difficulty: ⭐⭐⭐)

    Implement a complete "page transition animation" system:

    1. Fade + slide animation when switching routes
    2. Three Types of Animations for Adding, Deleting, and Sorting Items in a List
    3. The "scale + fade" combination for modal pop-ups
    4. Complex Timeline Animations with GSAP Integration
    5. Comparative Testing of 5 Third-Party Animation Libraries
    6. Performance Optimization (GPU Acceleration + will-change)
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏