Transitions and Animations
By Syncfusion®, Inc. · Last updated
The <Transition> component and its six CSS classes, named transitions, transition modes, CSS animations, custom class names, JavaScript hooks and :css="false", transitions between components, reusable transitions, <TransitionGroup> with keys, tag and move classes, state-driven animation and reduced motion.
Movement Helps People Follow
- When something appears or disappears suddenly, people can miss it.
- A short fade or slide shows what changed and where.
- Vue's
<Transition>adds CSS classes at the right moments when an element enters or leaves. - You write the CSS. Vue decides when each class is on.
Simple lesson: <Transition> adds classes while an element enters or leaves. Your CSS animates them.
A Real-World Example
- Meera's site shows a "Added to cart" message after each order.
- It should fade in, then fade out, not just pop.
- What happened: the message faded in, waited, then faded out.
name="fade"made Vue use classes that start withfade-.
What You Will Learn
- The six transition classes and when they apply.
- Named transitions.
- Transition modes for switching elements.
- CSS keyframe animations.
- Custom class names, for CSS libraries.
- JavaScript hooks.
- Transitions between components, and reusable transitions.
- Animating lists with
<TransitionGroup>. - Animating numbers from state, and respecting reduced motion.
The Six Classes
<Transition>works on one element or component that is added or removed byv-if,v-show,:isor akeychange.Entering:
v-enter-from: the start. Added before the element appears, removed one frame later.v-enter-active: the whole enter phase. Put thetransitionhere.v-enter-to: the end state.
- Leaving:
v-leave-from,v-leave-active,v-leave-to. - With
name="fade",v-becomesfade-. - Around a component, that component must have one root element, or nothing animates.
- Add
appearto animate the first show when the page loads, too.
Animation: a box fades in from opacity 0 while the classes fade-enter-from, fade-enter-active and fade-enter-to light up on a timeline, then fades out while the leave classes light up
toast
enter-from enter-active (transition here) enter-to leave-from leave-active leave-to
Enter: from → to while active. Leave: from → to while active. Then Vue removes the element.
Vue switches the classes. The transition on the active class does the moving.
Slide and Fade Together
Simple lesson: put transition on -active, and the hidden look on -enter-from and -leave-to.
<Transition> only animates. It does not add or remove anything by itself. The v-if, v-show or :key inside it decides that.
Switching Elements and Modes
<Transition>can switch between elements withv-if/v-else, or by changing akey.- By default, the old one leaves while the new one enters, at the same time.
mode="out-in": the old one leaves first, then the new one enters. Usually the nicest.mode="in-out": the new one enters first. Rarely used.
- What happened: changing the
keymade Vue treat it as a new element, so it animated.
CSS Animations and Custom Classes
- You can use
@keyframesanimations instead of transitions. Putanimationon the-activeclass. - Custom class props replace the default names:
enter-active-class,leave-active-classand the rest. - This is how you use a CSS animation library, such as Animate.css, with Vue.
Simple lesson: mode="out-in" for clean swaps. Custom classes connect CSS libraries.
JavaScript Hooks
<Transition>emits events at each step:@before-enter,@enter,@after-enter,@enter-cancelled, and the same for leave.@enter(el, done)and@leave(el, done)must calldone()when the animation finishes.- Add
:css="false"to tell Vue not to look for CSS classes. It is faster for pure JavaScript animation. - Here the browser's Web Animations API (
el.animate) does the work.
With :css="false", you must call done() in @enter and @leave. If you forget, Vue never finishes the transition, and a leaving element is never removed.
Components and Reusable Transitions
<Transition>works around a component, or around<component :is>and<RouterView>'s slot.- To reuse one transition everywhere, wrap it in your own component and pass the content through a slot.
Simple lesson: JavaScript hooks for full control. A small wrapper component makes a transition reusable.
TransitionGroup
<TransitionGroup>animates items in av-forlist as they are added, removed or moved.- Every item needs a unique
key. tag="ul"makes the group render a real<ul>around the items.- The extra
-moveclass animates items sliding to their new place. - Give leaving items
position: absolute, so the others can slide smoothly.
State-Driven Animation
- Some animations follow a number, not an element entering or leaving.
- Bind it to a style and add a CSS
transition. The browser animates the change. - Or move a number smoothly yourself with
requestAnimationFramein a watcher.
Some people feel sick from motion. Respect their system setting with CSS: @media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }. Keep transitions short, around 150 to 400 ms.
Simple lesson: <TransitionGroup> animates lists. For numbers, animate the style or the value.
TL;DR
<Transition>= animates one element entering or leaving.- Six classes =
v-enter-from/active/to,v-leave-from/active/to. name="fade"= class names start withfade-.mode="out-in"= the old element leaves before the new one enters.- Custom classes =
enter-active-classand friends, for CSS libraries. - JavaScript hooks =
@enter(el, done),@leave(el, done),:css="false". <TransitionGroup>= animatesv-forlists. Needs keys.tag,-move.- State-driven = bind styles with a CSS transition, or tween the number.
- Reduced motion = turn animations off for
prefers-reduced-motion.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
Two elements in one <Transition> | It animates both | One root only. Use v-if/v-else or :key | A warning, no animation |
transition on -enter-from | Any class works | Put transition on -active | The element jumps without animating |
No key when content changes | Vue sees the change | Add :key so Vue sees a new element | No animation on text change |
Forgetting done() | Vue knows when JS ends | Call done() in @enter/@leave | Leaving elements stay forever |
No position: absolute on leaving list items | Lists slide by themselves | Add it to -leave-active | Items jump instead of sliding |
| Long, flashy animations | More motion is better | 150 to 400 ms, respect reduced motion | Slow, tiring, or sickening pages |
Check Yourself
Exercises
What to Remember
<Transition>adds enter and leave classes. Your CSS does the animation.- Put
transitionon-active, the hidden look on-enter-fromand-leave-to. - Use
mode="out-in"and:keyfor clean swaps. - JavaScript hooks must call
done().<TransitionGroup>animates keyed lists. - Keep motion short, and respect reduced motion.
Next: Render Functions and Component Patterns