Skip to the solution
MediumFrontend11 min read

How do Transition and TransitionGroup work?

1.1k views

The problem

Question presented to candidate: "Design wants the notification panel to fade in and out, and items in the to-do list to slide when they are added, removed or reordered. Walk me through how Vue's <Transition> and <TransitionGroup> make that happen, and what you would check if an animation does not play."

What a strong answer should cover:

  • <Transition> animates one element or component entering or leaving (via v-if, v-show, a dynamic component or a changing key).
  • The six classes v-enter-from / -active / -to and v-leave-from / -active / -to, prefixed by name, and the timing: -from is applied first and swapped for -to on the next frame.
  • Vue detects the end from the element's computed transitionend / animationend timing, or from an explicit :duration; JavaScript hooks (@enter, @leave with a done callback) are the alternative.
  • mode="out-in" sequences two elements so they do not overlap.
  • <TransitionGroup> handles lists: each child needs a key, it can render a wrapper with tag, and it animates moves with the v-move class using the FLIP technique.
  • The animation itself is CSS run by the browser; Vue only toggles classes and removes the element at the right time.

Clarifying questions expected:

  • "Is this one element appearing and disappearing, or a list whose items reorder?"
  • "Do we need to respect prefers-reduced-motion?"

Code / implementation expected: Yes β€” a <Transition> with the CSS classes, and a <TransitionGroup> list with enter, leave and move styles.

  • transition
  • animation

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

11 min read Β· 10 sections

Read the code

VueTransition with an explicit duration, logging every hook and class change
<script setup>
import { ref } from "vue";
const show = ref(false);
const log = (hook) => (el) => console.log(`  hook ${hook.padEnd(12)} class="${el.className}"`);
</script>

<template>
  <button @click="show = !show">Toggle</button>
  <!-- duration given explicitly, so Vue times the transition itself -->
  <Transition name="fade" :duration="200"
    @before-enter="log('before-enter')($event)" @enter="log('enter')($event)" @after-enter="log('after-enter')($event)"
    @before-leave="log('before-leave')($event)" @leave="log('leave')($event)" @after-leave="log('after-leave')($event)">
    <p v-if="show" class="box">Hello</p>
  </Transition>
</template>

<style>
.fade-enter-active, .fade-leave-active { transition: opacity 0.2s ease; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
</style>
VueTransitionGroup list with enter, leave and move styles
<script setup>
import { ref } from "vue";
let nextId = 4;
const items = ref([{ id: 1, text: "Milk" }, { id: 2, text: "Eggs" }, { id: 3, text: "Bread" }]);
const add = () => items.value.splice(1, 0, { id: nextId++, text: `Item ${nextId - 1}` });
const remove = (id) => (items.value = items.value.filter((i) => i.id !== id));
const shuffle = () => (items.value = [...items.value].reverse());
</script>

<template>
  <button class="add" @click="add">Add</button>
  <button class="shuffle" @click="shuffle">Reverse</button>
  <!-- tag="ul": TransitionGroup renders a real element; every child needs a key -->
  <TransitionGroup name="list" tag="ul" :duration="300">
    <li v-for="item in items" :key="item.id" @click="remove(item.id)">{{ item.text }}</li>
  </TransitionGroup>
</template>

<style>
.list-enter-active, .list-leave-active { transition: all 0.3s ease; }
.list-enter-from, .list-leave-to { opacity: 0; transform: translateX(30px); }
.list-move { transition: transform 0.3s ease; }
.list-leave-active { position: absolute; }
</style>

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 22 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextMedium

What is the difference between ref and reactive?

Continue