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.
<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:
<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
.
<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:
<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.