Apply smooth transitions between non/visible HTML elements in Vue 3 with v-if

Video thumbnail

When we create our first interfaces or components in Vue, the HTML part when showing or hiding a block using conditionals or v-show could feel abrupt… until I understood how to use transitions with v-if. Since then, every time I want to elevate the user experience, I turn to the <transition> component because it is flexible, elegant, and really easy to apply.

Below, I explain everything you need to master these conditional transitions: from the basics to patterns and advanced micro-interactions.

What are Transitions in Vue and why they matter when using v-if

In Vue, transitions are a declarative way to animate the entry and exit of an element from the DOM. And when I say entry and exit, I'm talking precisely about what happens when you use v-if: the block completely appears or disappears from the DOM.

In my case, the first time I animated a block with v-if, I realized I had a very powerful tool in my hands: any content can be displayed with a smooth effect as it is mounted or unmounted from the DOM. And the best part is that it all depends on CSS, or JS hooks if you want to go further.

Difference between v-if and v-show in animations

  • v-if → mounts/unmounts the node, so transitions have complete enter and leave phases. Perfect for complete animations.
  • v-show → only alters display: none, so it does not unmount the element. It is useful for simple opacity animations, but not for complex transitions.

What controls the enter / leave cycle

Vue automatically generates classes like:

  • xxx-enter-from → initial state upon appearing
  • xxx-enter-active → transition applied upon entering
  • xxx-enter-to → final state

And their leave-* equivalents upon exiting.

How the <transition> component works step by step

The <transition> component wraps any element you want to animate. You only need to give it a name, and Vue will generate the classes with that prefix.

CSS classes that Vue automatically generates

If your transition is named fade-slide, Vue will generate:

  • .fade-slide-enter-from
  • .fade-slide-enter-active
  • .fade-slide-enter-to
  • .fade-slide-leave-from
  • .fade-slide-leave-active
  • .fade-slide-leave-to

Prefixes, suffixes, and transition names

I like to use semantic names:

  • fade
  • slide
  • fade-slide
  • scale-up

The component looks clean, and your CSS speaks for itself.

Practical Example: Animating a Block with v-if using fade-slide

With Vue, we can perform all kinds of developments, which includes being able to show content, content that we can display with smooth transitions of all types where what we can do with CSS is the limit.

The example looks like this:

<transition name="fade-slide">
   <div class="mycard-primary mb-5 block max-w-96" v-if="CONDITION">
       <div class="mycard-body">
           <h3 class="text-xl mb-3 ml-4">Add this item</h3>
           <cart-item :post="post" />
       </div>
   </div>
</transition>
***
<style>
.fade-slide-enter-active,
.fade-slide-leave-active {
   transition: all 0.4s ease;
}

.fade-slide-enter-from,
.fade-slide-leave-to {
   opacity: 0;
   transform: translateY(20px);
}

.fade-slide-enter-to,
.fade-slide-leave-from {
   opacity: 1;
   transform: translateY(0);
}
</style>

On my blog, I have a lot of material on Animations and Transitions in CSS, but these are, as they say, the rules.

The trick is that <transition> wraps a single root element. If you need to animate more than one, use <transition-group>.

The condition -CONDITION- specifies when the element is hidden or shown and, based on the transition we are implementing, how it will be shown and hidden.

Transitions in Vue are very simple: for the HTML element, we use the transition tag with a name (in this example, fade-slide), and for the CSS, we define classes that use the name of the transition tag as a prefix and suffixes such as -enter-active and -leave-active to indicate the behavior when showing/hiding the HTML element.

The rest of the classes are to specify the behavior of when it is shown or hidden, where imagination is the limit.

Common Errors when animating conditional elements

What I consider to be the most common errors:

  • Putting the v-if outside the <transition>
  • Forgetting to define the *-enter-from and *-leave-to classes
  • Not including a transition: in *-active
  • Using v-if in lists when it should be transition-group

Frequently Asked Questions about transitions with v-if in Vue

  1. Can transitions be used with v-if and v-show equally?
    1. No. v-if mounts/unmounts; v-show does not. That completely changes the animation.
  2. Why isn't my transition working with v-if?
    1. Check that <transition> wraps the root element, that the name matches, and that your classes have transition:.
  3. How do I avoid a sudden jump when showing elements?
    1. Ensure a defined initial state in enter-from.
  4. When to use CSS and when to use JS hooks?
    1. CSS for most cases; JS hooks for animations dependent on layout or advanced calculations.

Conclusion

Animating elements with v-if in Vue is one of those things that seems complex but is actually very straightforward. Personally, every time I apply conditional transitions, the interface gains fluidity and users feel a more polished experience. All it takes is understanding the enter/leave cycle and mastering a couple of CSS patterns.

If you are animating modals, cards, menus, or any element that appears/disappears, using <transition> with v-if will simplify your work immensely.

I agree to receive announcements of interest about this Blog.

Master transitions in Vue.js with v-if. Learn step-by-step how to animate the appearance and disappearance of elements to create smooth interfaces and improve user experience. This tutorial covers the `` component, CSS classes, practical examples, and common mistakes.

| 👤 Andrés Cruz

🇪🇸 En español