Easy Tutorial
❮ Vue Examples Vuejs Reactive ❯

Vue.js Transitions & Animations

In this chapter, we will mainly discuss Vue.js's transition effects and animation effects.


Transitions

Vue provides various ways to apply transition effects when inserting, updating, or removing DOM elements.

Vue offers a built-in transition wrapper component, which is used to wrap components that need to implement transition effects.

Syntax Format

<transition name="nameoftransition">
   <div></div>
</transition>

We can understand how Vue's transitions are implemented through the following example:

Example

<div id="databinding">
<button v-on:click="show = !show">Click Me</button>
<transition name="fade">
    <p v-show="show" v-bind:style="styleobj">Animation Example</p>
</transition>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#databinding',
    data: {
        show: true,
        styleobj: {
            fontSize: '30px',
            color: 'red'
        }
    },
    methods: {
    }
});
</script>

In the example, clicking the "Click Me" button toggles the value of the variable show between true and false. If show is true, the content of the <p> tag is displayed.

The following code shows the transition tag wrapping the <p> tag:

<transition name="fade">
    <p v-show="show" v-bind:style="styleobj">Animation Example</p>
</transition>

The transition is essentially a fade-in and fade-out effect. Vue provides 6 classes to switch between during the element's display and hide transitions:

For these class names that switch during the transition, if you use a <transition> without a name, v- is the default prefix for these class names. If you use <transition name="my-transition">, then v-enter will be replaced with my-transition-enter.

v-enter-active and v-leave-active can control different easing curves for entering/leaving transitions, which will be demonstrated in the following sections.

CSS Transitions

Typically, we use CSS transitions to achieve the effects.

Here is an example:

Example

<div id="databinding">
<button v-on:click="show = !show">Click Me</button>
<transition name="slide-fade">
    <p v-if="show">hello</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>

CSS Animations

CSS animations are similar to CSS transitions, but the v-enter class name is not removed immediately after the node is inserted into the DOM; instead, it is removed when the animationend event is triggered.

Example

<div id="databinding">
<button v-on:click="show = !show">Click Me</button>
<transition name="bounce">
    <p v-if="show">Hello</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>
<button v-on:click="show = !show">Click Me</button>
<transition name="bounce">
    <p v-if="show">tutorialpro.org -- Learning is not just about technology, it's about dreams!!!</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>

Custom Transition Classes

We can customize transition classes with the following attributes:

Custom transition classes have higher priority than normal classes, allowing for seamless integration with third-party libraries like animate.css.

Example

<div id="databinding">
<button v-on:click="show = !show">Click Me</button>
<transition
    name="custom-classes-transition"
    enter-active-class="animated tada"
    leave-active-class="animated bounceOutRight"
>
    <p v-if="show">tutorialpro.org -- Learning is not just about technology, it's about dreams!!!</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>

Using Both Transitions and Animations

Vue needs to attach event listeners to know when a transition is finished. It can be either transitionend or animationend, depending on the CSS rules applied. If you use either, Vue can automatically detect the type and set up the listeners.

However, in some cases, you might need to apply both transition and animation effects to the same element, such as when an animation quickly triggers and completes, but the transition effect is still ongoing. In such scenarios, you need to use the type attribute and set it to either animation or transition to explicitly declare the type Vue should listen for.

Explicit Transition Duration

In many cases, Vue can automatically determine the timing of the transition completion. By default, Vue waits for the first transitionend or animationend event on the root element of the transition. However, this can be overridden—for example, when you have a carefully orchestrated series of transitions, some of which are nested and have delays or longer durations than the root element.

In such cases, you can customize an explicit transition duration (in milliseconds) on the <transition> component:

&lt;transition :duration="1000">...</transition>

You can also specify separate durations for entering and leaving:

&lt;transition :duration="{ enter: 500, leave: 800 }">...</transition>

JavaScript Hooks

JavaScript hooks can be declared in attributes:

HTML Code:

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"

  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>

JavaScript Code:

// ...
methods: {
  // --------
  // ENTERING
  // --------

  beforeEnter: function (el) {
    // ...
  },
  // This callback function is optional
// Used in conjunction with CSS
enter: function (el, done) {
  // ...
  done()
},
afterEnter: function (el) {
  // ...
},
enterCancelled: function (el) {
  // ...
},

// --------
// Leaving
// --------

beforeLeave: function (el) {
  // ...
},
// This callback function is optional
// Used in conjunction with CSS
leave: function (el, done) {
  // ...
  done()
},
afterLeave: function (el) {
  // ...
},
// leaveCancelled is only used with v-show
leaveCancelled: function (el) {
  // ...
}
}

These hooks can be used in conjunction with CSS transitions/animations or used individually.

When using JavaScript transitions exclusively, call the done function. Otherwise, they will be called synchronously, and the transition will complete immediately.

It is recommended to add v-bind:css="false" for elements that use JavaScript transitions exclusively. Vue will skip CSS detection, which also prevents CSS from affecting the transition.

A simple example using Velocity.js:

Example

<div id="databinding">
<button v-on:click="show = !show">Click Me</button>
<transition
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
    v-bind:css="false"
  >
    <p v-if="show">tutorialpro.org -- Not just learning technology, but also dreams!!!</p>
</transition>
</div>
<script type="text/javascript">
new Vue({
  el: '#databinding',
  data: {
    show: false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.transformOrigin = 'left'
    },
    enter: function (el, done) {
      Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
      Velocity(el, { fontSize: '1em' }, { complete: done })
    },
    leave: function (el, done) {
      Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
        rotateZ: '45deg',
        translateY: '30px',
        translateX: '30px',
        opacity: 0
      }, { complete: done })
    }
  }
})
</script>

Initial Render Transition

You can set transitions for the initial render using the appear attribute:

&lt;transition appear>
  <!-- ... -->
</transition>

By default, it uses the same transitions as enter/leave, and you can also customize the CSS class names:

&lt;transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class" (2.1.8+)
  appear-active-class="custom-appear-active-class"
>
  <!-- ... -->
</transition>

Custom JavaScript hooks:

&lt;transition
  appear
  v-on:before-appear="customBeforeAppearHook"
  v-on:appear="customAppearHook"
  v-on:after-appear="customAfterAppearHook"
  v-on:appear-cancelled="customAppearCancelledHook"
>
  <!-- ... -->
</transition>
<transition
  v-on:before-appear="customBeforeAppearHook"
  v-on:appear="customAppearHook"
  v-on:after-appear="customAfterAppearHook"
  v-on:appear-cancelled="customAppearCancelledHook"
>
  <!-- ... -->
</transition>

Transition for Multiple Elements

We can set up transitions for multiple elements, typically lists and descriptions:

It's important to note that when switching elements with the same tag name, you need to set a unique value using the key attribute to mark them so that Vue can distinguish between them. Otherwise, Vue will optimize efficiency by only replacing the content inside the same tags.

<transition>
  <table v-if="items.length > 0">
    <!-- ... -->
  </table>
  &lt;p v-else>Sorry, the content you are looking for was not found.</p>
</transition>

Example:

<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  &lt;button v-else key="edit">
    Edit
  </button>
</transition>

In some scenarios, you can also use the key attribute of the same element to set different states instead of using v-if and v-else. The above example can be rewritten as:

<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>

Transitions for multiple elements with multiple v-if conditions can be rewritten as a single element transition with dynamic attributes. For example:

<transition>
  <button v-if="docState === 'saved'" key="saved">
    Edit
  </button>
  <button v-if="docState === 'edited'" key="edited">
    Save
  </button>
  <button v-if="docState === 'editing'" key="editing">
    Cancel
  </button>
</transition>

Can be rewritten as:

<transition>
  <button v-bind:key="docState">
    {{ buttonMessage }}
  </button>
</transition>

// ...
computed: {
  buttonMessage: function () {
    switch (this.docState) {
      case 'saved': return 'Edit'
      case 'edited': return 'Save'
      case 'editing': return 'Cancel'
    }
  }
}
❮ Vue Examples Vuejs Reactive ❯