Menu Close

Vue.js Transition Effects — List Transitions

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to add transitions when rendering lists.

List Transitions

If we want to apply transitions to render multiple items simultaneously with v-for , we can use the transition-group component.

Unlike transition , it renders a span by default. We can change the element that’s rendered with the tag attribute.

Transition modes aren’t available because we aren’t alternating between mutually exclusive elements.

Elements inside are always required to have a unique key attribute.

CSS transition classes will be applied to inner elements and not the group or container itself.

List Entering/Leaving Transitions

For example, we can make add a transition when adding or removing the item to a list as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    items: [1, 2, 3],  
    nextNum: 4  
  },  
  methods: {  
    add() {  
      this.items.push(this.nextNum++);  
    },  
    remove() {  
      this.items.pop();  
    }  
  }  
});

src/style.css :

.list-enter-active,  
.list-leave-active {  
  transition: all 1s;  
}  
.list-enter,  
.list-leave-to {  
  opacity: 0;  
  transform: translateY(30px);  
}

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <link  
      rel="stylesheet"  
      type="text/css"  
      href="./src/styles.css"  
      media="screen"  
    />  
  </head>  
  <body>  
    <div id="app">  
      <button @click="add">Add</button>  
      <button @click="remove">Remove</button>  
      <transition-group name="list" tag="p">  
        <span v-for="item in items" :key="item">  
          {{ item }}  
        </span>  
      </transition-group>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then when we click the Add button, we see a number added to the end of the list. When we click Remove, the rightmost number is removed.

Like transition , we defined the classes prefixed with the name we specified.

Also, we specified the tag name so that we have a span element rendered for each item within the p element.

List Move Transitions

transition-group can animate the change in position, in addition, to enter and leave. We can do this with the addition of the v-move class.

Like other classes, we prefix it with the name attribute and we can also manually specify a class with the move-class attribute.

For example, we can add an effect when we shuffle the position of numbers as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    items: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
  },  
  methods: {  
    shuffle() {  
      this.items = _.shuffle(this.items);  
    }  
  }  
});

src/styles.css :

.flip-list-move {  
  transition: transform 1s;  
}

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>  
    <link rel="stylesheet" type="text/css" href="./src/styles.css" />  
  </head>  
  <body>  
    <div id="app">  
      <button @click="shuffle">Shuffle</button>  
      <transition-group name="flip-list" tag="div">  
        <div v-for="item in items" :key="item">  
          {{ item }}  
        </div>  
      </transition-group>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

When we click Shuffle, we see the shuffling is stretched slightly in time.

Vue uses FLIP to smoothly transition between elements from the old position to their new position.

They don’t work with elements set to display: inline , we have to use display: inline-block or place elements in a flexbox container.

Staggering List Transitions

We can stagger list transitions as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    items: ["foo", "bar", "baz"],  
    query: ""  
  },  
  computed: {  
    filteredItems() {  
      if (!this.query) {  
        return this.items;  
      }  
      return this.items.filter(i => i === this.query);  
    }  
  },  
  methods: {  
    beforeEnter(el) {  
      el.style.opacity = 0;  
      el.style.height = 0;  
    },  
    enter(el, done) {  
      var delay = el.dataset.index * 150;  
      setTimeout(() => {  
        Velocity(el, { opacity: 1, height: "1.6em" }, { complete: done });  
      }, delay);  
    },  
    leave(el, done) {  
      var delay = el.dataset.index * 150;  
      setTimeout(() => {  
        Velocity(el, { opacity: 0, height: 0 }, { complete: done });  
      }, delay);  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <input v-model="query" />  
      <transition-group  
        name="flip-list"  
        tag="div"  
        v-bind:css="false"  
        v-on:before-enter="beforeEnter"  
        v-on:enter="enter"  
        v-on:leave="leave"  
      >  
        <div v-for="item in filteredItems" :key="item">  
          {{ item }}  
        </div>  
      </transition-group>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

We can see that we now have transitions when the list is being filtered.

Conclusion

We can create transitions when rendering a list with v-for like we do with v-if .

The difference is that we have to specify the tag name of the container if we don’t want to render a span.

Also, we always have to add the key attribute to each element inside.

We can have transitions when changing element position by specifying the CSS style for the v-move class, which can be renamed if we specify the class prefix or name.

Specifying enter and leave transitions or v-for is the same as specifying enter and leave transitions for v-if .

Finally, we can create transitions with JavaScript with Velocity.js just like v-if animations.

Posted in vue