The Motion component is the primary building block for animations in Motion for Vue. It can be rendered as any HTML or SVG element by using the as prop, such as <Motion as="div"/> or <Motion as="circle"/>. Alternatively, you can pass asChild to render a child component directly.
import { Motion } from 'motion-v'
< Motion
as = "div"
class = "w-10 h-10 bg-primary rounded-lg"
: initial = " {
opacity: 0
} "
: animate = " {
opacity: 1
} "
/>
< script setup lang = "ts" >
</ script >
< template >
< Motion
class = "bg-primary w-1/3 aspect-square rounded-2xl"
: initial = " { scale: 0 } "
: animate = " { rotate: 180 , scale: 1 } "
: transition = " {
type: 'spring' ,
stiffness: 260 ,
damping: 20 ,
delay: 0.3 ,
} "
/>
</ template >
Set a value as an array and Motion will animate through each of these values in turn.
By default, each keyframe will be spaced evenly throughout the animation, but the exact timing and easing can be configured via the transition property.
< script setup lang = "ts" >
import { Motion } from 'motion-v'
</ script >
< template >
< Motion
class = "bg-primary h-20 aspect-square rounded-2xl"
: animate = " {
scale: [ 1 , 2 , 2 , 1 , 1 ],
rotate: [ 0 , 0 , 180 , 180 , 0 ],
borderRadius: [ '0%' , '0%' , '50%' , '50%' , '0%' ],
} "
: transition = " {
duration: 2 ,
ease: 'easeInOut' ,
times: [ 0 , 0.2 , 0.5 , 0.8 , 1 ],
repeat: Infinity ,
repeatDelay: 1 ,
} "
/>
</ template >
Variants are pre-defined visual states that a component can be in. By giving a component and its children variants with matching names, whole Vue trees can be animated by changing a single prop.
< script setup lang = "ts" >
import { Motion } from 'motion-v'
const container = {
hidden: { opacity: 1 , scale: 0 },
visible: {
opacity: 1 ,
scale: 1 ,
},
}
const items = {
hidden: { y: 20 , opacity: 0 , scale: 0.85 },
visible: {
y: 0 ,
opacity: 1 ,
},
}
const list = [ 0 , 1 , 2 , 3 ]
</ script >
< template >
< Motion
as = "ul"
: variants = " container "
initial = "hidden"
animate = "visible"
: transition = " {
type: 'spring' ,
delayChildren: 0.5 ,
staggerChildren: 0.2 ,
} "
class = "rounded-2xl overflow-hidden list-none p-2 grid-cols-2 grid-rows-2 aspect-square bg-primary/20 w-1/3 grid"
>
< Motion
v-for = " (item, i) in list "
: key = " item "
: variants = " items "
class = "bg-primary rounded-full origin-center"
/>
</ Motion >
</ template >
Motion provides hover, press helper props, that will temporarily animate a component to a visual state while a gesture is active.
Like animate, these can either be set as an object of properties (each with their own transition prop), or the name of a variant.
< script setup lang = "ts" >
import { Motion } from 'motion-v'
</ script >
< template >
< Motion
: hover = " { scale: 1.2 , rotate: 90 } "
: press = " {
scale: 0.8 ,
rotate: - 90 ,
borderRadius: '100%' ,
} "
: transition = " {
type: 'spring' ,
stiffness: 260 ,
damping: 20 ,
} "
as = "button"
class = "rounded-2xl overflow-hidden list-none p-2 grid-cols-2 grid-rows-2 aspect-square bg-primary w-1/3 grid"
/>
</ template >
The inView prop to set a component to animate when it enters the viewport.
< script setup lang = "ts" >
import { Motion } from 'motion-v'
</ script >
< template >
< Motion
class = "bg-primary w-1/3 aspect-square rounded-2xl"
: initial = " { scale: 0 } "
: in-view = " { rotate: 180 , scale: 1 } "
: in-view-options = " {
once: true ,
} "
: transition = " {
type: 'spring' ,
stiffness: 260 ,
damping: 20 ,
delay: 0.3 ,
} "
/>
</ template >
The initial visual state of the Motion component.
This can be set as an animation target:
< Motion
: initial = " {
opacity: 0 ,x: 0
} "
/>
or set a string to target a variant:
< Motion
initial = "variantName"
: variants = " {
variantName: {
opacity: 0 ,x: 0
}
} "
/>
or set false to disable the initial animation:
< Motion
: initial = " false "
/>
the animate prop is used to set the animation target. When the component is mounted or the animate prop is updated, it will animate to the animate target.
< Motion
: animate = " {
opacity: 1 ,x: 100
} "
/>
or set a string to target a variant:
< Motion
animate = "variantName"
: variants = " {
variantName: {
opacity: 1 ,x: 100
}
} "
/>
The custom prop is used to pass through to dynamic variants.
< script setup lang = "ts" >
import { Motion } from 'motion-v'
import type { Variant } from 'motion-v'
const variants : Record < string , Variant | (( custom : number ) => Variant )> = {
invisible: {
opacity: 0 ,
y: 20 ,
},
visible : custom => ({
opacity: 1 ,
y: 0 ,
transition: { delay: custom * 0.3 , ease: 'easeInOut' , duration: 0.4 },
}),
}
</ script >
< template >
< Motion
as = "ul"
initial = "invisible"
animate = "visible"
class = "space-y-4 w-1/2"
>
< Motion
v-for = " i in 3 "
: key = " i "
as = "li"
: custom = " i - 1 "
: variants = " variants "
class = "h-10 bg-primary rounded-lg "
/>
</ Motion >
</ template >
The transition prop is used to set the transition of the animation.
< Motion
: initial = " { x: 0 , opacity: 0 } "
: animate = " { x: 100 , opacity: 1 } "
: transition = " {
duration: 1 ,
x: { type: 'spring' , stiffness: 260 , damping: 20 },
} "
/>
The inViewOptions prop is used to set the options for the inView prop.
< Motion
: in-view-options = " {
once: true ,
} "
/>
Default: 0
The margin option allows you to set the margin around the component that should be in view for the animation to trigger.
< Motion
: in-view = " { x: 0 } "
: in-view-options = " { margin: 100 } "
/>
Default: false
The once option allows you to set the animation to trigger only once when the component enters the viewport.
< Motion
: in-view = " { x: 0 } "
: in-view-options = " { once: true } "
/>
The root option allows you to set the root element that the inView animation should be relative to.
< Motion
: in-view = " { x: 0 } "
: in-view-options = " { root: '#root' } "
/>
Default: some
The amount option allows you to set the amount of the component that should be in view for the animation to trigger.
You can set the amount to all, which means the animation will trigger when the entire component is in view.
or you can set a number, which means the animation will trigger when the component is in view by the amount of the component that is in view.
< Motion
: in-view = " { x: 0 } "
: in-view-options = " { amount: 'all' } "
/>
The as prop allows you to set the HTML or SVG element that the Motion component should be rendered as.
< Motion
as = "div"
class = "w-10 h-10 bg-primary rounded-lg"
/>
The asChild prop allows you to render a child component directly.
< Motion
as-child
>
<ChildComponent />
</ Motion >
if you use asChild,and the ChildComponent's root dom is SVGElement, you should set the as prop to determine the dom element type.