
How to use Vue Transition Component without v-if
In this article we want to explore how we can use vue transition component without using v-if by using v-show.
Introduction
As you know Vue has 2 built-in components (Transition and TransitionGroup) that help you to make transitions and animation based on state changes.
Most Vue.js, developers traditionally use v-if with the Transition component to create animated element appearances and disappearances.
While
v-ifworks well, it completely removes elements from the DOM, which can sometimes lead to unnecessary re-rendering and performance overhead and also SEO issues.
The Typical Way to use Transition Component
The typical pattern involves conditionally rendering an element using v-if inside a Transition wrapper.
When the show data property toggles, the element appears and disappears with a fade effect.
<!-- Traditional Approach with v-if -->
<template>
<div>
<button @click="show = !show">Toggle Element</button>
<!-- we named the transition so instead of v-leave-to we refer to fade-leave-to -->
<Transition name="fade">
<div v-if="show">
<p>I'm here!</p>
</div>
</Transition>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const show = ref(false)
</script>
<style>
.fade-enter-active,
.fade-leave-active {
opacity: 1;
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0.01;
transition: opacity 0.5s ease;
}
</style>
Problem
But the problem is that show is false and the <p>I'm here!</p> will not appear in HTML❗
What we can do?
Short answer: set true as default value of show state.
What if we want to have default value of false 🤔?
That's when v-show comes into play!
Better Approach: Using v-show with appear
appearprop helps us to apply transition on the initial render.
<template>
<div>
<button @click="show = !show">Toggle Element</button>
<transition name="fade" appear>
<div v-show="show">
<p>I'm here!</p>
</div>
</transition>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const show = ref(false)
</script>
<style>
.fade-appear-active,
.fade-enter-active,
.fade-leave-active {
opacity: 1;
transition: opacity 0.5s ease;
}
.fade-appear-from,
.fade-enter-from,
.fade-leave-to {
opacity: 0.01;
transition: opacity 0.5s ease;
}
</style>
Now we have <p>I'm here!</p> element on the initial render of HTML.
The key difference is how they handle element rendering:
v-ifcompletely removes the element from the DOM when the condition is falsev-showsimply toggles the CSSdisplayproperty, keeping the element in the DOMv-ifhas higher toggle costs but lower initial render costsv-showhas lower toggle costs but slightly higher initial render costs
Choose v-if when:
- The condition rarely changes
- You want to save resources by not rendering unnecessary elements
- The element won't be toggled frequently
- You're working with heavy components that shouldn't be kept in memory
Choose v-show when:
- The element will be toggled frequently
- You want to maintain the element's state
- Performance of quick toggling is more important
- You need smoother animations
Yes, You can combine multiple CSS classes and properties:
<template>
<Transition
appear
appear-class="custom-appear"
appear-active-class="active-appear"
appear-to-class="to-appear">
<div v-show="isVisible">
Complex Transition Content
</div>
</Transition>
</template>
This allows granular control over initial render animations, letting you define specific classes for different stages of the appear transition.
v-iftriggers full component destruction and re-creation- Calls
beforeUnmountandunmountedhooks - Completely reinitializes the component on re-render
v-showkeeps the component instance alive- Only toggles visibility
- Maintains component state and avoids unnecessary re-initialization
- More efficient for frequently toggled elements
For complex scenarios, and performance optimization consider using the v-if and v-show combination.
<template>
<Transition name="fade">
<div v-if="shouldRender" v-show="isVisible">
Optimized Conditional Content
</div>
</Transition>
</template>
- Prevents initial rendering of unnecessary elements (
v-if) - Provides smooth toggling (
v-show) - Minimizes unnecessary DOM manipulations and re-creation.