At NOVA LAB we have many panels — the reactor diagnostics panel slides in from the side, the alerts panel appears with a fade effect, and the navigation panel drops from above. Vue lets you name Transitions, which changes the CSS class prefixes and allows you to define many different animations in a single application.
By default,
<Transition> uses the v- prefix for CSS classes. The name attribute changes this prefix to a chosen name:1<Transition name="slide">
2 <div v-if="visible">...</div>
3</Transition>Now the classes are:
slide-enter-from, slide-enter-active, slide-enter-to, slide-leave-from, slide-leave-active, slide-leave-to.1.slide-enter-active,
2.slide-leave-active {
3 transition: all 0.3s ease;
4}
5.slide-enter-from {
6 opacity: 0;
7 transform: translateX(30px);
8}
9.slide-leave-to {
10 opacity: 0;
11 transform: translateX(-30px);
12}Thanks to named transitions, you can have multiple animation types simultaneously:
1<template>
2 <!-- Reactor panel — slides in from the right -->
3 <Transition name="slide-right">
4 <div v-if="showReactor">Reactor Panel</div>
5 </Transition>
6
7 <!-- Alert — appears with a fade effect -->
8 <Transition name="fade">
9 <div v-if="showAlert">Alert!</div>
10 </Transition>
11
12 <!-- Menu — drops from above -->
13 <Transition name="slide-down">
14 <nav v-if="showMenu">Navigation</nav>
15 </Transition>
16</template>1/* Fade */
2.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; }
3.fade-enter-from, .fade-leave-to { opacity: 0; }
4
5/* Slide from right */
6.slide-right-enter-active, .slide-right-leave-active { transition: all 0.4s ease; }
7.slide-right-enter-from { transform: translateX(100%); opacity: 0; }
8.slide-right-leave-to { transform: translateX(100%); opacity: 0; }
9
10/* Slide from top */
11.slide-down-enter-active, .slide-down-leave-active { transition: all 0.3s ease; }
12.slide-down-enter-from { transform: translateY(-100%); opacity: 0; }
13.slide-down-leave-to { transform: translateY(-100%); opacity: 0; }When switching between two elements within a single
<Transition>, both animate simultaneously by default — the old one leaves while the new one enters at the same time. This often looks chaotic. The mode attribute controls the order:mode="out-in" — the old element leaves and only after its animation finishes does the new one enter. This is the most commonly used mode — it prevents layout "jumping."mode="in-out" — the new element enters, and the old one leaves only afterward. Rarely used, but useful for overlay effects.1<template>
2 <div class="view-switcher">
3 <button @click="currentView = currentView === 'status' ? 'alerts' : 'status'">
4 Switch View
5 </button>
6
7 <Transition name="fade" mode="out-in">
8 <div v-if="currentView === 'status'" key="status" class="panel">
9 System Status: All nominal
10 </div>
11 <div v-else key="alerts" class="panel">
12 Active Alerts: 3
13 </div>
14 </Transition>
15 </div>
16</template>
17
18<script setup>
19import { ref } from 'vue'
20
21const currentView = ref('status')
22</script>Important: When switching elements of the same HTML type (e.g., two
<div> elements), you must use :key so that Vue knows they are different elements and should trigger a transition animation. Without :key, Vue will optimize rendering and skip the animation.mode="out-in" works great with dynamic components:1<template>
2 <Transition name="slide" mode="out-in">
3 <component :is="currentTab" />
4 </Transition>
5</template>
6
7<script setup>
8import { shallowRef } from 'vue'
9import StatusPanel from './StatusPanel.vue'
10import AlertsPanel from './AlertsPanel.vue'
11
12const currentTab = shallowRef(StatusPanel)
13</script>For simple view switching,
mode="out-in" with a fade animation is the most elegant solution. Avoid mode="in-out" unless you have a specific reason (e.g., an overlapping slide effect). No mode works mainly when both elements have position: absolute and don't affect the layout.