Animate4vue is a library for ready-to-use animations designed for Vue.js applications, featuring over 100 high-performance UI animations crafted with GSAP, offering GPU-accelerated rendering with better performance and efficiency across all devices, as well as callbacks and async handling. Unlike traditional CSS animation libraries that can be tasking and less efficient on low-end devices, Animate4vue make your animations look and feel flawless.
Offers TypeScript support, and tree-shaking, so only the animations you use are bundled, keeping your application lean and fast.
Why Animate4vue Was Created
Traditional CSS animations often struggle with performance issues, especially on less powerful devices, due to their heavy reliance on the browser's rendering engine π. To overcome these limitations, Animate4vue uses GSAP, a robust JavaScript animation library that provides smooth, GPU-accelerated animations π¨. GSAP's efficiency and power ensure that animations remain fluid and responsive, regardless of device capabilities, making it an ideal choice for modern web applications βοΈ. Additionally, JavaScript animations offer greater control, including callbacks and async functionality, enhancing flexibility and precision in your projects π―.
Features
- π¨ 100+ Animations: A diverse set of animations for various UI elements.
- π GSAP-Powered: Smooth, GPU-accelerated animations for enhanced performance.
- π TypeScript Support: Fully typed for better development experience.
- π³ Tree-Shaking: Includes only the animations you use, keeping your bundle size minimal.
- π Fine-grained Control: Offer callbacks for animation state, and asynchronous handling.
You can install Animate4vue via npm or yarn:
npm install animate4vue
or
yarn add animate4vue
Animate4vue seamlessly integrates with Vue's <Transition>
and <TransitionGroup>
components, giving you the flexibility to add animations with ease. There are two primary methods for incorporating animations with these components:
This involves applying animations directly by hooking into the lifecycle events of Transition components. Hereβs how you can do it:
<script setup>
import { puffIn, puffOut } from 'animate4vue';
</script>
<template>
<Transition @enter="puffIn" @leave="puffOut">
<div v-if="show">....</div>
</Transition>
</template>
Important: When using Vue with TypeScript, it's recommended to use the Function Invocation method for handling animations. This is due to type incompatibilities when directly hooking animations onto the
<Transition>
component.
Important: Elements should be conditionally displayed using v-if for animations to work.
Tip: Make sure there are no animations or CSS transitions applied or conflicting with elements to animate, they might interfere and mess things up. For example, avoid specifying CSS transitions globally.
To animate elements on initial load, use the appear
directive to trigger animations without conditional rendering with v-if
:
<template>
<Transition appear @enter="zoomInLeft" @leave="zoomOutRight">
<div>....</div>
</Transition>
</template>
Through 'direct invocation,' you can specify animation options by setting dataset attributes like so:
<Transition @enter="flipInHorizontalLeft" @leave="zoomOutLeft" data-av-leave-ease="backIn" data-av-offset="100%">
<div v-if="show">....</div>
</Transition>
data-av-[option property]="..."
The datasets attributes can be applied directly to the
<Transition>
tag or the element inside it, giving you more flexibility:
β
<Transition ... data-av-ease="backIn">
β
<div v-if="show" data-av-ease="elastic">
Options using dataset attributes apply to both @enter and @leave animations except data-av-enter-ease and data-av-leave-ease.
This method involves handling animations within the <script>
, offering greater control, such as adding fallbacks and handling async
operations. When working with Vue and TypeScript, this approach is recommended to avoid type errors that can occur when directly applying animations to the <Transition>
component.
<script setup>
import { zoomIn, zoomOut } from 'animate4vue';
const animateIn = (el, done) => {
zoomIn(el, done)
}
const animateOut = (el, done) => {
zoomOut(el, done)
}
// The 'done' argument is used to signal Vue about the animation state and then update the DOM.
</script>
<template>
<Transition @enter="animateIn" @leave="animateOut">
<div v-if="show">....</div>
</Transition>
</template>
Important: Always pass the done as a second argument, needed to tell Vue to remove the element out the DOM when animation is finished.
When using function invocation, you can pass options as a configuration object to the third parameter of the animation:
const animateIn = (el, done) => {
zoomIn(el, done, {
duration: 2,
// Callbacks for animation state
onStart: doSomething(),
onComplete: () => alert('Done!)
})
}
Function invocation also support setting options through dataset attributes in template.
You may use the <TransitionGroup>
for animating multiple elements as they enter and leave the DOM:
<TransitionGroup @enter="slideInRight" @leave="slideInLeft">
<li v-for="item in list" :key="item">....</li>
</TransitionGroup>
Vue's transition components also provide a range of callback events, giving you finer control over the animation lifecycle. These include events like before-enter, after-enter, enter-cancelled, before-leave, after-leave, and leave-cancelled. Here's an example of how to use these callbacks:
<script setup>
const animationEnded = (el) => {
console.log('Animation is finished!')
}
</script>
<template>
<Transition @enter="vanishIn" @after-enter="animationEnded"></Transition>
</template>
All animations return a Promise that resolves when the animation completes, allowing you to handle asynchronous operations using await
or by chaining .then()
and .catch()
:
const animateIn = async (el, done) => {
await zoomIn(el, done)
}
// or
zoomIn(el, done).then(() => console.log('Success'))
.catch((error) => console.log(error))
Name | Default | Type | Usage |
---|---|---|---|
duration | 0.4 |
number |
{duration: 2} , `data-av-duration="2"`` |
delay | 0 |
number |
{delay: 1} , data-av-delay="1" |
fade | 0.1 |
number |
{fade: 0.5} , `data-av-fade="1"`` |
blur | 0 |
number |
{blur: 3} , `data-av-blur="2"`` |
ease | "ease" |
string |
{ease: "linear"} , data-av-ease="backOut" |
offset | "100%" of element's width |
string |
{offset: "150px"} , data-av-offset="150px" |
onStart | undefined |
function |
{onStart: ()=> action()} |
onComplete | undefined |
function |
{onComplete: ()=> action()} |
data-av-enter-ease | "ease" |
string |
data-av-enter-ease="bounceIn" |
data-av-leave-ease | "ease" |
string |
data-av-leave-ease="elasticIn" |
- type:
number
- default:
0.4
Duration of the animation in seconds. Numbers below 0 denotes milliseconds(e.g 0.3).
- type:
number
- default:
0
Delay before the animation starts in seconds. Numbers below 0 denotes milliseconds(e.g 0.3).
- type:
number
- default:
0.1
Indicates the starting opacity (for 'enter' animations) and ending opacity (for 'leaving' animations). Accepts
0
to1
. e.g.0.5
- type:
number
- default:
0
Applies a blur effect to the animation. The higher the value, the more pronounced the blur.
- type:
string
- default:
"linear"
Easing effect of the animation.
See values
Value | Effect |
---|---|
linear |
Constant speed throughout the animation. |
easeIn |
Starts slowly and accelerates towards the end. |
easeOut |
Starts quickly and decelerates towards the end. |
ease |
Starts slowly, accelerates, and then decelerates. |
bounceIn |
Bounces in from the start, creating a bouncing effect as it enters. |
bounceOut |
Bounces out towards the end, creating a bouncing effect as it exits. |
bounce |
Combines both bounceIn and bounceOut effects. |
backIn |
Moves in with a slight overshoot and then comes back, creating a "back" effect. |
backOut |
Moves out with a slight overshoot before settling. |
back |
Combines both backIn and backOut effects. |
elasticIn |
Starts slowly, accelerates, and then returns with a slight elastic effect. |
elasticOut |
Starts quickly, decelerates, and then returns with an elastic effect. |
elastic |
Combines both elasticIn and elasticOut effects. |
- type:
string
- default:
"100%"
Defines the initial distance from which the animation should begin/end. Only applicable to animations involving movement in right, left, up & down. Like rotateInRight, slideOutBottom. Does not allow negative values e.g "-50vh". Will fallback to default (100%).
See values
Value | Description |
---|---|
0 |
Dont move. |
100px |
Moves the element 100 pixels from/to its initial position. Can be any number. |
50% |
Moves the element 50% of its own width (for right/left ) or height (for up/down ). |
100vw |
Moves the element 100% of the viewport width (for right/left ). |
100vh |
Moves the element 100% of the viewport height (for up/down ). |
- type:
function
- default:
undefined
Callback function executed when the animation starts.
- type:
function
- default:
undefined
Callback function executed when the animation finishes.
- type:
function
- default:
"ease"
Easing effect of the 'enter' animation when setting option through dataset attributes e.g data-av-enter-ease="easeOut". Easing values
- type:
function
- default:
"ease"
Easing effect of the 'leave' animation when setting option through dataset attributes e.g data-av-leave-ease="backIn". Easing values
When using both function invocation and dataset options for an animation, remember that function invocation options take precedence. This means only the dataset attributes not covered by the function invocation will be applied. For instance:
<script setup>
import { rollIn, rollOut } from 'animate4vue';
const animateIn = (el, done) => {
rollIn(el, done, {
duration: 3,
ease: "elastic"
})
}
</script>
<template>
<Transition @enter="animateIn" @leave="rollOut" data-av-duration="1" data-av-enter-ease="linear" data-av-delay="1">
<div v-if="show">...</div>
</Transition>
</template>
π In this example, only the data-av-delay option from dataset attributes will be applied, as the duration and ease options are specified in the function invocation.
See all animations
-
Fade animations
- fadeIn, fadeOut
-
Slide animations
- slideInRight, slideInLeft, slideInTop, slideInBottom, slideInTopRight, slideInTopLeft, slideInBottomRight, slideInBottomLeft, slideOutRight, slideOutLeft, slideOutTop, slideOutBottom, slideOutTopRight, slideOutTopLeft, slideOutBottomRight, slideOutBottomLeft
-
Wrap animations
- wrapInVertical, wrapOutVertical, wrapInHorizontal, wrapOutHorizontal
-
Flip animations
- flipInHorizontal, flipOutHorizontal, flipInVertical, flipOutVertical, flipInHorizontalRight, flipInHorizontalLeft, flipInHorizontalTop, flipInHorizontalBottom, flipOutHorizontalRight, flipOutHorizontalLeft, flipOutHorizontalTop, flipOutHorizontalBottom, flipInVerticalRight, flipInVerticalLeft, flipInVerticalTop, flipInVerticalBottom, flipOutVerticalRight, flipOutVerticalLeft, flipOutVerticalTop, flipOutVerticalBottom
-
Zoom animations
- zoomIn, zoomInRight, zoomInLeft, zoomInTop, zoomInBottom, zoomInTopRight, zoomInTopLeft, zoomInBottomRight, zoomInBottomLeft, zoomOut, zoomOutRight, zoomOutLeft, zoomOutTop, zoomOutBottom, zoomOutTopRight, zoomOutTopLeft, zoomOutBottomRight, zoomOutBottomLeft
-
Rotation animations
- rotateIn, rotateInBottomLeft, rotateInBottomRight, rotateInTopLeft, rotateInTopRight, rotateOut, rotateOutBottomLeft, rotateOutBottomRight, rotateOutTopLeft, rotateOutTopRight
-
Skew animations
- skewInRight, skewInLeft, skewOutRight, skewOutLeft
-
Roll animations
- rollIn, rollOut
-
Puff animations
- puffIn, puffOut
-
Vanish animations
- vanishIn, vanishOut
-
Blur animations
- blurIn, blurOut
-
Perspective animations
- perspectiveInRight, perspectiveInLeft, perspectiveInTop, perspectiveInBottom, perspectiveOutRight, perspectiveOutLeft, perspectiveOutTop, perspectiveOutBottom
-
Open and Close animations
- openTopLeft, openTopRight, openBottomLeft, openBottomRight, closeTopLeft, closeTopRight, closeBottomLeft, closeBottomRight
-
Text animations
- textIn, textOut
Attention seekers are animations designed to grab users' attention, such as a ringing bell icon or shaking elements. These animations enhance user engagement and provide a compelling experience. Animate4vue offers a variety of dynamic attention-seeking animations to fit any scenario.
puff
, jello
, spin
, bounce
, pulse
, flash
, rubberBand
, headShake
, shakeHorizontal
, shakeVertical
, swing
, tada
, wobble
, heartBeat
. More coming...
<script setup>
import { swing } from 'animate4vue';
import { ref } from 'vue';
const el = ref(null)
const ringBell = () => {
swing(el)
// You can also use any HTML selector such as '#target' or '.class' etc.
}
</script>
<template>
<img ref="el" src="bell.png" />
<button @click="ringBell">Ring</button>
</template>
You can pass options to customize the animation behavior. For example:
headShake(el, {
loop: true,
durattion: 2,
delay: 1
})
Name | Default | Type |
---|---|---|
loop | false |
boolean |
duration | 0.5 - 1.5 |
number |
delay | 0.111 |
number |
- type:
boolean
- default:
false
Indicator wether the animation should repeat or not..
- type:
number
- default: defer by animation:
0.5
to1.5
Duration of the animation in seconds. Numbers below 0 denotes milliseconds(e.g 0.3).
- type:
number
- default:
0.111
Delay before the animation in seconds. Numbers below 0 denotes milliseconds(e.g 0.3). Also specify repeat delay of the animation when is on loop.
Attention seekers provide a kill()
method to stop ongoing animations, especially when set to loop. This allows you to halt the animation at any time.
<script setup>
import { rubberBand } from 'animate4vue';
import { ref, onMounted } from 'vue';
let animation = null
const ringBell = () => {
// Start the rubberBand animation with looping enabled
animation = swing('#target', { loop: true })
}
const stopRingBell = () => {
// Stop the currently running animation
if (animation) animation.kill()
}
// Optionally start animation when the component mounts
onMounted(() => {
animation = rubberBand('#target', { loop: true })
})
</script>
<template>
<img id="target" src="bell.png" />
<button @click="ringBell">Ring</button>
<button @click="stopRingBell">Stop</button>
</template>
Important: Be cautious when triggering an animation, as it cannot be stopped once initiated if triggered multiple times.
Important: Additionally, a new animation cannot be started on an element that already has an ongoing animation.
Tip: Attention seeker animations also work with Transition component events. For example
@enter="jello"
.
Animate4vue offers a flexible customAnimation
method, allowing you to define your own animations dynamically.
<script setup>
import { customAnimation } from 'animate4vue';
const animateIn = (el, done) => {
customAnimation(el, done, "enter", {
duration: 2,
keyframes: [
{ scaleX: 1, scaleY: 1, duration: 0.1 },
{ scaleX: 1.25, scaleY: 0.75, duration: 0.1 }
],
ease: "power1.inOut"
})
}
</script>
<template>
<Transition @enter="animateIn">
...
</Transition>
</template>
customAnimation(element, done, direction, config)
Parameters:
- element
- The DOM element to animate.
- done
- Callback required by Vue to signal that the animation is complete and the element can be removed from the DOM.
- direction
- Specifies whether the animation is for entering or leaving.
- Values:
"enter"
: For animations when the element is entering."leave"
: For animations when the element is leaving.
- config
- Configuration object for the animation. Accepts any GSAP properties, if you're familiar with GSAP then fire on!
Keep in mind that the animation properties defined for 'enter' dictate how the element appears when it enters, while those specified for 'leave' determine how it disappears.
The customAnimation()
method returns a Promise that resolves when the animation is complete, allowing you to use await
or chain .then()
and .catch()
for asynchronous operations:
const animateIn = async (el, done) => {
await customAnimation(el, done, "enter", {
// animation configuration
});
}
// or
customAnimation(el, done, "leave", {
// animation configuration
}).then(() => console.log('Animation Complete'))
.catch((error) => console.log('Animation Error:', error));
If you have feature requests, encounter any issues or bugs, or have suggestions for improving the code, please open an issue on the GitHub repository.
This project is distributed under the MIT License.