Search code examples
vuejs2vue-transitions

Why does this simple transition on toggling elements with `v-if` not work?


If i try a very simple example with two <div>'s, only one of which is showing at a time by using v-if, the out-in transition doesn't fade between them.

<div id="app">
  <transition name="fade" mode="out-in">
    <div v-if="(box==='a')">a</div>
    <div v-if="(box==='b')">b</div>
  </transition>

  <button @click="box='a'">show a</button>
  <button @click="box='b'">show b</button>
</div>

And my CSS code for the animation:

.fade-enter-active, .fade-leave-active {
    transition: opacity .3s ease;
}
.fade-enter, .fade-leave-to {
    opacity: 0;
}

JSFiddle located here: https://jsfiddle.net/3ckto1am/1/


Solution

  • You can set the "div box" to a boolean value & then create a method which toggles the boolean between true/false like so:

    Template:

    <div id="app">
      <transition name="fade" mode="out-in">
        <div v-if="boxA" key="boxA">Div A</div>
        <div v-else key="boxB">Div B</div>
      </transition>
      
      <button @click="toggleBoxes">Toggle div boxes!</button>
    </div>
    

    JavaScript:

    new Vue({
      el: "#app",
      data: {
        boxA: true
      },
      methods: {
        toggleBoxes() {
            this.boxA = !this.boxA;
        }
      }
    })
    

    Edit:

    As for the <transition>, when toggling between elements that have the same tag name, you must tell Vue that they are distinct elements by giving them unique key attributes (key='<uniqueKey>') to the tag elements, you can read about it here.

    You can check this working code sample.

    However, if you still want to have two buttons to toggle the <div>, check this code instead.

    Furthermore, I highly suggest you to read the official documentation on Conditional Rendering with Vuejs.