Due to the many features that have to be worked on, sometimes we forget to give animation effects to the components we create. Even though it doesn't have a big impact on the user experience, animation effects can make our application look more interesting and interactive. Apart from that, animation effects can also help users understand changes that occur in the application. Vue.js provides a transition feature using the Transition component which makes it easier for us to provide animation effects to components.

In this article I use tailwindcss as a utility class to create animations.

Component Appearing / Disappearing Animation

The Transition component in Vue.js is actually sufficient to provide animation effects on components, but because there are many props that have to be written, we will create our own simpler component. I named this component ToggleTransition.vue which will have three props, namely duration, type and timingFunction. You can put it in the src/components folder of your Vue.js project.

html
        
<script setup lang="ts">
import { computed } from 'vue';

const props = withDefaults(defineProps<{
  duration: 'fast' | 'normal' | 'slow';
  type: 'fade' | 'slideX' | 'slideY' | 'zoomIn' | 'zoomOut';
  timingFunction: 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear';
}>(), {
  duration: 'normal',
  type: 'fade',
  timingFunction: 'ease-in'
});

const transitionClassesMap = {
  slideY: {
    enterFromClass: 'opacity-0 translate-y-20',
    enterToClass: 'opacity-100 translate-y-0',
    leaveFromClass: 'opacity-100 translate-y-0',
    leaveToClass: 'opacity-0 translate-y-20',
  },
  slideX: {
    enterFromClass: 'opacity-0 translate-x-20',
    enterToClass: 'opacity-100 translate-x-0',
    leaveFromClass: 'opacity-100 translate-x-0',
    leaveToClass: 'opacity-0 translate-x-20'
  },
  zoomIn: {
    enterFromClass: 'opacity-0 scale-50',
    enterToClass: 'opacity-100 scale-100',
    leaveFromClass: 'opacity-100 scale-100',
    leaveToClass: 'opacity-0 scale-50'
  },
  zoomOut: {
    enterFromClass: 'opacity-0 scale-150',
    enterToClass: 'opacity-100 scale-100',
    leaveFromClass: 'opacity-100 scale-100',
    leaveToClass: 'opacity-0 scale-150'
  },
  fade: {
    enterFromClass: 'opacity-0',
    enterToClass: 'opacity-100',
    leaveFromClass: 'opacity-100',
    leaveToClass: 'opacity-0'
  },
};

const transitionClasses = computed(() => transitionClassesMap[props.type]);
const durationMap = {
  fast: 'duration-300',
  normal: 'duration-700',
  slow: 'duration-1000'
};

</script>

<template>
  <Transition appears
    :enter-active-class="`transition ${props.timingFunction} ${durationMap[props.duration]}`"
    :enter-from-class="transitionClasses.enterFromClass"
    :enter-to-class="transitionClasses.enterToClass"
    :leave-active-class="`transition ${props.timingFunction} ${durationMap[props.duration]}`"
    :leave-from-class="transitionClasses.leaveFromClass"
    :leave-to-class="transitionClasses.leaveToClass">
    <slot></slot>
  </Transition>
</template>
      

The ToggleTransition component above accepts three props, namely duration, type and timing-function. duration is used to determine the duration of the animation, while type is used to determine the type of animation to be used (fade, slideY, slideX, zoomIn, zoomOut). timingFunction is used to specify the type of timing function used in the animation.

Example of using the ToggleTransition component:

html
        
<script setup lang="ts">
import { ref } from 'vue';
import ToggleTransition from './components/ToggleTransition.vue';

const state = ref(true);
</script>

<template>
  <button @click="state = !state" class="bg-yellow-700 rounded m-5 text-white p-4">Toggle State</button>

  <ToggleTransition type="slideY" duration="slow">
    <div v-if="state" class="bg-blue-500 text-white p-4 mb-2">Slide Y</div>
  </ToggleTransition>

  <ToggleTransition type="fade" timing-function="ease-in">
    <div v-if="state" class="bg-blue-500 text-white p-4 mb-2">Fade</div>
  </ToggleTransition>
</template>
      

The Toggle State button is used to change the value of the state variable which will show or hide elements within the ToggleTransition component. In the example above, we use two types of animation, namely slideY and fade.

Animation Between Components

Apart from animations appearing and disappearing, we can also provide animation effects when components change. For example, when we replace a block in an application, we can provide an animation effect when the old component is replaced by a new component. We will also create our own component called SwitchTransition.vue which will also have three props, namely duration, type and timingFunction.

html
        
<script setup lang="ts">
import { computed } from 'vue';

const props = withDefaults(defineProps<{
  duration: 'fast' | 'normal' | 'slow';
  type: 'fade' | 'slideX' | 'slideY' | 'zoom';
  timingFunction: 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear';
}>(), {
  duration: 'normal',
  type: 'fade',
  timingFunction: 'ease-in'
});

const transitionClassesMap = {
  slideY: {
    enterFromClass: 'opacity-0 translate-y-20',
    enterToClass: 'opacity-100 translate-y-0',
    leaveFromClass: 'opacity-100 translate-y-0',
    leaveToClass: 'opacity-0 translate-y-20',
  },
  slideX: {
    enterFromClass: 'opacity-0 translate-x-20',
    enterToClass: 'opacity-100 translate-x-0',
    leaveFromClass: 'opacity-100 translate-x-0',
    leaveToClass: 'opacity-0 translate-x-20'
  },
  zoom: {
    enterFromClass: 'opacity-0 scale-50',
    enterToClass: 'opacity-100 scale-100',
    leaveFromClass: 'opacity-100 scale-100',
    leaveToClass: 'opacity-0 scale-50'
  },
  fade: {
    enterFromClass: 'opacity-0',
    enterToClass: 'opacity-100',
    leaveFromClass: 'opacity-100',
    leaveToClass: 'opacity-0'
  }
};

const transitionClasses = computed(() => transitionClassesMap[props.type]);
const durationMap = {
  fast: 'duration-300',
  normal: 'duration-700',
  slow: 'duration-1000'
};
const enterLeaveActiveClass = computed(() => `transition ${props.timingFunction} ${durationMap[props.duration]}`);
</script>

<template>
  <Transition 
    :enter-active-class="enterLeaveActiveClass" 
    :enter-from-class="transitionClasses.enterFromClass"
    :enter-to-class="transitionClasses.enterToClass"
    :leave-active-class="enterLeaveActiveClass"
    :leave-from-class="transitionClasses.leaveFromClass"
    :leave-to-class="transitionClasses.leaveToClass"
    mode="out-in">

    <slot></slot>
  
  </Transition>
</template>
      

The SwitchTransition component above is almost the same as the ToggleTransition component, but we use the mode="out-in" property in the Transition component. This property is used to provide an animation effect on old components before they are replaced by new components. To use this component it must be ensured that only 1 component is displayed at a time.

Example of using the SwitchTransition component:

html
        
<script setup lang="ts">
import { ref } from 'vue';
import SwitchTransition from './components/SwitchTransition.vue';

const state = ref(true);
</script>

<template>
  <button @click="state = !state" class="bg-yellow-700 rounded m-5 text-white p-4">Toggle State</button>

  <SwitchTransition type="slideY" duration="slow">
    <div v-if="state" class="bg-blue-500 text-white p-4 mb-2">Slide Y</div>
    <div v-else class="bg-red-500 text-white p-4 mb-2">Slide Y</div>
  </SwitchTransition>

  <SwitchTransition type="fade" timing-function="ease-in">
    <div v-if="state" class="bg-blue-500 text-white p-4 mb-2">Fade</div>
    <div v-else class="bg-red-500 text-white p-4 mb-2">Fade</div>
  </SwitchTransition>
</template>
      

In the example above, we use two types of animation, namely slideY and fade. When the Toggle State button is pressed, the components displayed will change with the animation effect that we specified.

Conclusion

Hopefully this article can help you in providing animation effects to the Vue.js components that you create. By using the Transition component in Vue.js, we can give animation effects to components easily. By giving animation effects to components, we can make our applications look more attractive and interactive.