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:

Success! Your changes have been saved.

🔹 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>

Output:

Photo Gallery

Sunset

🧠 Test Your Knowledge

How does v-show hide elements?