🎭 Vue.js List Transitions: The Magic Show for Your Lists!
Imagine You’re a Stage Director… 🎬
Picture this: You’re running a talent show. When new performers walk onto stage, they don’t just appear out of thin air — they walk in gracefully! And when they leave? They wave goodbye and exit smoothly, not vanish like ghosts.
That’s exactly what TransitionGroup does for lists in Vue!
Without TransitionGroup, adding or removing items from a list is like blinking — one moment it’s there, the next it’s gone. Boring! With TransitionGroup, every item gets its own dramatic entrance and exit.
🌟 What is TransitionGroup?
Think of <TransitionGroup> as a magic wrapper for lists. It watches every item in your list and says:
“Hey little item, when you enter — do a spin! When you leave — fade away gracefully!”
The Simple Truth:
<Transition>= For ONE thing entering/leaving<TransitionGroup>= For MANY things (lists!) entering/leaving
🎪 Your First TransitionGroup: The Basics
Let’s build a simple to-do list where items smoothly appear and disappear!
<template>
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</TransitionGroup>
</template>
Wait, What’s That tag Thing? 🤔
Great question! Unlike regular <Transition>, TransitionGroup actually creates a real HTML element.
tag="ul"→ Creates a<ul>wrappertag="div"→ Creates a<div>wrapper- No tag? → Defaults to a
<span>
graph TD A["TransitionGroup tag=&#39;ul&#39;"] --> B["Creates ul Element"] B --> C["li item 1"] B --> D["li item 2"] B --> E["li item 3"]
🔑 The Golden Rule: Every Item Needs a Key!
SUPER IMPORTANT: Every item inside TransitionGroup MUST have a unique :key
Think of keys like name tags at a party. Vue uses them to know:
- “Oh, THIS is Jake! He’s new — make him enter dramatically!”
- “Sam left? Time for his exit animation!”
<!-- ✅ CORRECT: Each item has unique key -->
<TransitionGroup name="fade" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</TransitionGroup>
<!-- ❌ WRONG: Using index as key -->
<li v-for="(item, index) in items" :key="index">
Why not use index? Because when you remove item 2, item 3 becomes the new “2” — Vue gets confused and animations break!
🎨 CSS Classes: The Animation Magic
TransitionGroup uses the same CSS classes as Transition, but applies them to each item:
| Class | When It’s Applied |
|---|---|
.list-enter-from |
Item about to appear |
.list-enter-active |
Item is appearing |
.list-enter-to |
Item finished appearing |
.list-leave-from |
Item about to disappear |
.list-leave-active |
Item is disappearing |
.list-leave-to |
Item finished disappearing |
Here’s the Complete CSS:
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
Translation: “When items enter or leave, take 0.5 seconds. Start invisible and shifted right, end visible and in place!”
🏃 The Move Transition: The Special Sauce!
Here’s something AMAZING that only TransitionGroup can do: Move Transitions!
When you add or remove an item, the OTHER items need to shuffle around, right? TransitionGroup can animate that too!
.list-move {
transition: transform 0.5s ease;
}
The .list-move class is applied to items that are changing position (not entering or leaving, just moving over to make room).
The Full Example:
.list-move,
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* CRITICAL: Make leaving items not affect layout */
.list-leave-active {
position: absolute;
}
Why position: absolute for leaving items?
Imagine someone leaving a line of people. If they slowly walk away while still “taking up space,” everyone else can’t move forward until they’re gone!
By making leaving items position: absolute, they “float” away while others smoothly fill the gap.
graph TD A["Item Leaves"] --> B{Has position: absolute?} B -->|Yes| C["Floats away, others slide smoothly"] B -->|No| D["Blocks space, jerky animation"]
🎯 Real-World Example: Shuffleable List
<template>
<button @click="shuffle">Shuffle!</button>
<button @click="add">Add Item</button>
<TransitionGroup name="flip" tag="ul">
<li v-for="item in items" :key="item">
{{ item }}
</li>
</TransitionGroup>
</template>
<script setup>
import { ref } from 'vue'
const items = ref([1, 2, 3, 4, 5])
function shuffle() {
items.value = items.value
.sort(() => Math.random() - 0.5)
}
function add() {
items.value.push(items.value.length + 1)
}
</script>
<style>
.flip-move {
transition: transform 0.8s ease;
}
</style>
When you click “Shuffle,” items gracefully dance to their new positions! 💃🕺
🎭 Staggered Animations: The Domino Effect
Want items to enter one-by-one like dominoes falling? Use data-index with JavaScript hooks!
<template>
<TransitionGroup
name="stagger"
tag="ul"
@before-enter="onBeforeEnter"
@enter="onEnter"
>
<li
v-for="(item, index) in items"
:key="item"
:data-index="index"
>
{{ item }}
</li>
</TransitionGroup>
</template>
<script setup>
function onBeforeEnter(el) {
el.style.opacity = 0
el.style.transform = 'translateY(30px)'
}
function onEnter(el, done) {
const delay = el.dataset.index * 100
setTimeout(() => {
el.style.transition = 'all 0.5s ease'
el.style.opacity = 1
el.style.transform = 'translateY(0)'
setTimeout(done, 500)
}, delay)
}
</script>
Each item waits a bit longer than the previous one before appearing. Item 1 = 0ms delay, Item 2 = 100ms, Item 3 = 200ms…
The result? A beautiful cascading waterfall effect! 🌊
📝 Quick Summary
| Feature | What It Does |
|---|---|
<TransitionGroup> |
Wrapper for animating list items |
tag="ul" |
Creates a real HTML element |
:key |
REQUIRED! Unique identifier for each item |
name="list" |
Prefix for CSS classes |
.list-move |
Animates items changing position |
position: absolute |
Prevents leaving items from blocking space |
🚀 You’ve Got This!
TransitionGroup is like giving each item in your list its own personal choreographer. New items enter with style, leaving items exit gracefully, and everyone shuffles around smoothly.
Remember these three things:
- 🔑 Always use unique
:key - 📦 Use
tagprop to set the wrapper element - 🏃 Use
.list-move+position: absolutefor smooth shuffling
Now go make those lists dance! 🎉
