What Causes This Warning?
This warning occurs when you provide an invalid value to the mode prop of Vue’s <Transition> component. Only in-out and out-in are valid mode values.
The Problem
<!-- ❌ Invalid mode values -->
<template>
<Transition mode="fade">
<Component />
</Transition>
<Transition mode="both">
<Component />
</Transition>
<Transition mode="inout">
<Component />
</Transition>
</template>
The Fix
Use Valid Mode Values
<template>
<!-- ✅ out-in: current element transitions out first, then new one in -->
<Transition mode="out-in">
<Component :key="componentKey" />
</Transition>
<!-- ✅ in-out: new element transitions in first, then current one out -->
<Transition mode="in-out">
<Component :key="componentKey" />
</Transition>
<!-- ✅ No mode: both transition simultaneously (default) -->
<Transition>
<Component :key="componentKey" />
</Transition>
</template>
Mode Comparison
No Mode (Default)
Both elements transition at the same time:
<template>
<Transition name="fade">
<Component :key="current" />
</Transition>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
out-in Mode (Most Common)
Old element leaves first, then new element enters:
<template>
<!-- ✅ Best for most use cases -->
<Transition name="fade" mode="out-in">
<Component :key="current" />
</Transition>
</template>
in-out Mode
New element enters first, then old element leaves:
<template>
<!-- Useful for specific effects like overlapping cards -->
<Transition name="slide" mode="in-out">
<Component :key="current" />
</Transition>
</template>
Common Scenarios
Tab Switching
<script setup>
import { ref } from 'vue'
const activeTab = ref('home')
</script>
<template>
<div class="tabs">
<button @click="activeTab = 'home'">Home</button>
<button @click="activeTab = 'about'">About</button>
</div>
<!-- ✅ Use out-in for clean tab transitions -->
<Transition name="fade" mode="out-in">
<HomeTab v-if="activeTab === 'home'" key="home" />
<AboutTab v-else key="about" />
</Transition>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
Route Transitions
<template>
<RouterView v-slot="{ Component, route }">
<Transition name="page" mode="out-in">
<component :is="Component" :key="route.path" />
</Transition>
</RouterView>
</template>
<style>
.page-enter-active,
.page-leave-active {
transition: all 0.3s ease;
}
.page-enter-from {
opacity: 0;
transform: translateX(20px);
}
.page-leave-to {
opacity: 0;
transform: translateX(-20px);
}
</style>
Dynamic Components
<script setup>
import { shallowRef } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
const current = shallowRef(ComponentA)
function toggle() {
current.value = current.value === ComponentA ? ComponentB : ComponentA
}
</script>
<template>
<button @click="toggle">Toggle</button>
<Transition name="slide" mode="out-in">
<component :is="current" />
</Transition>
</template>
Slide Transition
<template>
<Transition name="slide" mode="out-in">
<div :key="step">
Step {{ step }} content
</div>
</Transition>
</template>
<style>
.slide-enter-active,
.slide-leave-active {
transition: all 0.3s ease;
}
.slide-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-leave-to {
transform: translateX(-100%);
opacity: 0;
}
</style>
Why Modes Exist
Without modes, both elements exist in the DOM during the transition, which can cause:
- Layout jumping (two elements taking space)
- Overlapping content
- Unpredictable visual results
Using mode="out-in" ensures only one element is visible at a time.
Quick Checklist
- Use only
out-inorin-outfor the mode prop -
out-inis usually what you want (old leaves, then new enters) -
in-outis for special effects (new enters, then old leaves) - No mode = simultaneous transitions
- Always use
:keyto trigger transitions between elements