Vue v-show
Toggle element visibility with CSS
👁️ What is v-show?
The v-show directive toggles element visibility using CSS display property. Unlike v-if, the element always stays in the DOM but is hidden with display: none when the condition is false.
<!-- v-show Example -->
<div id="app">
<p v-show="isVisible">I can be toggled!</p>
<button @click="isVisible = !isVisible">
Toggle Visibility
</button>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
Vue.createApp({
data() {
return {
isVisible: true
}
}
}).mount('#app')
</script>
Output:
I can be toggled!
v-show vs v-if
v-show
Uses CSS display property
<!-- Always in DOM -->
<p v-show="show">
Text
</p>
v-if
Adds/removes from DOM
<!-- Removed if false -->
<p v-if="show">
Text
</p>
Performance
v-show: Low toggle cost
<!-- Fast toggling -->
<div v-show="toggle">
Content
</div>
Initial Render
v-if: Lazy rendering
<!-- Not rendered -->
<div v-if="false">
Heavy
</div>
🔹 Basic v-show Usage
The v-show directive is perfect for frequently toggled elements. It simply changes the CSS display property, keeping the element in the DOM for fast show/hide operations.
<div id="app">
<h3>Notification Panel</h3>
<div v-show="showNotification" style="padding: 15px; background: #e7f5ff; border: 1px solid #42b883; border-radius: 5px;">
<p>You have {{ messageCount }} new messages!</p>
</div>
<button @click="showNotification = !showNotification">
{{ showNotification ? 'Hide' : 'Show' }} Notifications
</button>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
Vue.createApp({
data() {
return {
showNotification: true,
messageCount: 5
}
}
}).mount('#app')
</script>
Output:
Notification Panel
You have 5 new messages!
🔹 When to Use v-show
Use v-show when you need to toggle elements frequently. Since it only changes CSS, there's minimal performance cost. It's ideal for tabs, dropdowns, modals, and other UI elements that toggle often.
<div id="app">
<div class="tabs">
<button @click="activeTab = 'home'" :class="{ active: activeTab === 'home' }">Home</button>
<button @click="activeTab = 'profile'" :class="{ active: activeTab === 'profile' }">Profile</button>
<button @click="activeTab = 'settings'" :class="{ active: activeTab === 'settings' }">Settings</button>
</div>
<div v-show="activeTab === 'home'" class="tab-content">
<h3>Home Content</h3>
<p>Welcome to the home page!</p>
</div>
<div v-show="activeTab === 'profile'" class="tab-content">
<h3>Profile Content</h3>
<p>Your profile information here.</p>
</div>
<div v-show="activeTab === 'settings'" class="tab-content">
<h3>Settings Content</h3>
<p>Adjust your preferences.</p>
</div>
</div>
<style>
.tabs button { padding: 10px 20px; margin-right: 5px; }
.tabs button.active { background: #42b883; color: white; }
.tab-content { padding: 20px; border: 1px solid #ddd; margin-top: 10px; }
</style>
<script src="https://unpkg.com/vue@3"></script>
<script>
Vue.createApp({
data() {
return {
activeTab: 'home'
}
}
}).mount('#app')
</script>
Output:
Home Content
Welcome to the home page!
🔹 When to Use v-if
Use v-if when the condition rarely changes or when you want to avoid rendering expensive components initially. It's better for conditional rendering that happens once or infrequently during the component lifecycle.
<div id="app">
<h3>User Access Control</h3>
<!-- Use v-if for rarely changing conditions -->
<div v-if="user.role === 'admin'">
<h4>Admin Panel</h4>
<p>Access to all system settings</p>
<button>Manage Users</button>
<button>View Reports</button>
</div>
<div v-else-if="user.role === 'editor'">
<h4>Editor Panel</h4>
<p>Content management access</p>
<button>Edit Content</button>
</div>
<div v-else>
<h4>User Panel</h4>
<p>Basic user access</p>
<button>View Content</button>
</div>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
Vue.createApp({
data() {
return {
user: {
role: 'admin'
}
}
}
}).mount('#app')
</script>
Output:
User Access Control
Admin Panel
Access to all system settings
🔹 Combining v-show with Transitions
The v-show directive works great with Vue transitions because the element stays in the DOM. You can create smooth fade-in and fade-out effects for better user experience.
<div id="app">
<button @click="showAlert = !showAlert">
Toggle Alert
</button>
<transition name="fade">
<div v-show="showAlert" class="alert">
<strong>Success!</strong> Your changes have been saved.
</div>
</transition>
</div>
<style>
.alert {
padding: 15px;
background: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 5px;
margin-top: 10px;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
<script src="https://unpkg.com/vue@3"></script>
<script>
Vue.createApp({
data() {
return {
showAlert: true
}
}
}).mount('#app')
</script>
Output:
🔹 Practical Example: Image Gallery
This example demonstrates v-show in a real-world scenario. The image details toggle quickly without re-rendering, making the gallery feel responsive and smooth for users browsing through images.
<div id="app">
<h3>Photo Gallery</h3>
<div class="gallery">
<div v-for="(photo, index) in photos" :key="index" class="photo-card">
<img :src="photo.url" :alt="photo.title" width="200">
<h4>{{ photo.title }}</h4>
<button @click="photo.showDetails = !photo.showDetails">
{{ photo.showDetails ? 'Hide' : 'Show' }} Details
</button>
<div v-show="photo.showDetails" class="details">
<p>{{ photo.description }}</p>
<p><small>Uploaded: {{ photo.date }}</small></p>
</div>
</div>
</div>
</div>
<style>
.gallery { display: flex; gap: 20px; }
.photo-card { border: 1px solid #ddd; padding: 15px; border-radius: 8px; }
.details { margin-top: 10px; padding: 10px; background: #f9f9f9; border-radius: 5px; }
</style>
<script src="https://unpkg.com/vue@3"></script>
<script>
Vue.createApp({
data() {
return {
photos: [
{
title: 'Sunset',
url: 'sunset.jpg',
description: 'Beautiful sunset over the ocean',
date: '2024-01-15',
showDetails: false
},
{
title: 'Mountains',
url: 'mountains.jpg',
description: 'Majestic mountain landscape',
date: '2024-01-20',
showDetails: false
}
]
}
}
}).mount('#app')
</script>