# Animation

Motion for Vue offers a number of ways to animate your UI. Scaling from extremely simple prop-based animations, to more complex orchestration.

## Basic animations

You'll perform almost all animations on [a](/docs/vue-motion-component.md) `[<motion />](/docs/vue-motion-component.md)` [component](/docs/vue-motion-component.md). This is basically a DOM element with motion superpowers.

```
import { motion } from "motion-v"
```

For basic animations, you can update values on [the](/docs/vue-motion-component#animate.md) `[animate](/docs/vue-motion-component#animate.md)` [prop](/docs/vue-motion-component#animate.md):

```
<motion.div :animate="{ opacity: 1 }" />
```

When any value in its animate prop changes, the component will automatically animate to the new target.

## Animatable values

Motion can animate any CSS value, even those that can't be animated by browsers, like `mask-image`. It supports:

*   Numbers: `0`, `100` etc.
    
*   Strings containing numbers: `"0vh"`, `"10px"` etc.
    
*   Colors: Hex, RGBA, HSLA.
    
*   Complex strings containing multiple numbers and/or colors (like `box-shadow`).
    
*   `display: "none"/"block"` and `visibility: "hidden"/"visible"`.
    

### Value type conversion

In general, values can only be animated between two of the same type (i.e `"0px"` to `"100px"`).

Colors can be freely animated between hex, RGBA and HSLA types.

Additionally, `x`, `y`, `width`, `height`, `top`, `left`, `right` and `bottom` can animate between different value types.

```
<motion.div
  :initial='{ x: "100%" }'
  :animate='{ x: "calc(100vw - 50%)" }'
/>
```

It's also possible to animate `width` and `height` in to/out of `"auto"`.

```
<motion.div
  :initial='{ height: "0px" }'
  :animate='{ height: "auto" }'
/>
```

**Note:** If additionally animating `display` in to/out of `"none"`, replace this with `visibility` `"hidden"` as elements with `display: none` can't be measured.

### Transforms

Unlike CSS, Motion can animate every transform axis independently:

*   Translate: `x`, `y`, `z`
    
*   Scale: `scale`, `scaleX`, `scaleY`
    
*   Rotate: `rotate`, `rotateX`, `rotateY`, `rotateZ`
    
*   Skew: `skew`, `skewX`, `skewY`
    
*   Perspective: `transformPerspective`
    

`motion` components have enhanced `style` props, allowing you to set individual transforms:

```
<motion.section :style="{ x: -20 }" />
```

Animating transforms independently provides great flexibility, especially around gestures.

```
<motion.button :whileHover="{ scale: 1.1 }" whilePress="{ scale: 0.9 }" />
```

Independent transforms perform great, but Motion's hybrid engine also uniquely offers hardware acceleration by setting `transform` directly.

```
<motion.li
  :initial='{ transform: "translateX(-100px)" }'
  :animate='{ transform: "translateX(0px)" }'
  :transition='{ type: "spring" }'
/>
```

**SVG note:** For SVG components, `x` and `y` **attributes** can be set using `attrX` and `attrY`.

### Transform origin

`transform-origin` has three shortcut values that can be set and animated individually:

*   `originX`
    
*   `originY`
    
*   `originZ`
    

If set as numbers, `originX` and `Y` default to a progress value between `0` and `1`. `originZ` defaults to pixels.

```
<motion.div :style='{ originX: 0.5 }' />
```

### CSS variables

Motion for Vue can animate the value of CSS variables, and also use CSS variables as animation targets.

#### Animating CSS variables

Sometimes it's convenient to be able to animate a CSS variable to animate many children:

```
<motion.ul
  :initial="{ '--rotate': '0deg' }"
  :animate="{ '--rotate': '360deg' }"
  :transition="{ duration: 2, repeat: Infinity }"
>
  <li :style="{ transform: 'rotate(var(--rotate))' }" />
  <li :style="{ transform: 'rotate(var(--rotate))' }" />
  <li :style="{ transform: 'rotate(var(--rotate))' }" />
</motion.ul>
```

**Note:** Animating the value of a CSS variable **always triggers paint**, therefore it can be more performant to use `[MotionValue](/docs/vue-motion-value.md)`[s](/docs/vue-motion-value.md) to setup this kind of animation.

### CSS variables as animation targets

HTML `motion` components accept animation targets with CSS variables:

```
<motion.li :animate="{ backgroundColor: 'var(--action-bg)' }" />
```

#### SVG line drawing

Line drawing animations can be created with many different SVG elements using three special properties: `pathLength`, `pathSpacing` and `pathOffset`.

```
<motion.path :initial="{ pathLength: 0 }" :animate="{ pathLength: 1 }" />
```

All three are set as a progress value between `0` and `1`, `1` representing the total length of the path.

Path animations are compatible with `circle`, `ellipse`, `line`, `path`, `polygon`, `polyline` and `rect` elements.

## Transitions

By default, Motion will create appropriate transitions for snappy animations based on the type of value being animated.

For instance, physical properties like `x` or `scale` are animated with spring physics, whereas values like `opacity` or `color` are animated with duration-based easing curves.

However, you can define your own animations via [the](/docs/vue-transitions.md) `[transition](/docs/vue-transitions.md)` [prop](/docs/vue-transitions.md).

```
<motion.div
  :animate="{ x: 100 }"
  :transition="{ ease: 'easeOut', duration: 2 }"
/>
```

## Enter animations

When a `motion` component is first created, it'll automatically animate to the values in `animate` if they're different from those initially rendered, which you can either do via CSS or via [the](/docs/vue-motion-component.md) `[initial](/docs/vue-motion-component.md)` [prop.](/docs/vue-motion-component.md)

```
<motion.li
  :initial="{ opacity: 0, scale: 0 }"
  :animate="{ opacity: 1, scale: 1 }"
/>
```

You can also disable the enter animation entirely by setting `:initial="false"`. This will make the element render with the values defined in `animate`.

```
<motion.div :initial="false" :animate="{ y: 100 }" />
```

## Exit animations

You can also easily animate elements as they exit the DOM.

In Vue, when a component is removed, it's usually removed instantly. Motion provides [the](/docs/vue-animate-presence.md) `[AnimatePresence](/docs/vue-animate-presence.md)` [component](/docs/vue-animate-presence.md) which keeps elements in the DOM while they perform an `exit` animation.

```
<AnimatePresence>
    <motion.div
      v-if="isVisible"
      key="modal"
      :initial="{ opacity: 0 }"
      :animate="{ opacity: 1 }"
      :exit="{ opacity: 0 }"
    />
</AnimatePresence>
```

## Keyframes

Values in `animate` can be set as a series of keyframes. This will animate through each value in sequence.

```
<motion.div :animate="{ x: [0, 100, 0] }" />
```

We can use a value's current state as the initial keyframe by setting it to `null`.

```
<motion.div :animate="{ x: [null, 100, 0] }" />
```

This way, if a keyframe animation is interrupting another animation, the transition will feel more natural.

By default, each keyframe is spaced naturally throughout the animation. You can override this by setting [the](/docs/vue-transitions#times.md) `[times](/docs/vue-transitions#times.md)` [option](/docs/vue-transitions#times.md) via `transition`.

`times` is an array of progress values between `0` and `1`, defining where in the animation each keyframe should be positioned.

```
<motion.circle
  :cx="500"
  :animate="{
    cx: [null, 100, 200],
    transition={{ duration: 3, times: [0, 0.2, 1] }}
  }"
/>
```

## Gesture animations

Motion for Vue has shortcut props for animating to/from a target when a gesture starts/ends.

```
<motion.button
  :initial="{ opacity: 0 }"
  :whileHover="{ backgroundColor: 'rgba(220, 220, 220, 1)' }"
  :whilePress="{ backgroundColor: 'rgba(255, 255, 255, 1)' }"
  :whileInView="{ opacity: 1 }"
/>
```

It supports `hover`, `press`, `drag`, `focus` and `inView`.

## Variants

Setting `animate` as a target is useful for simple, single-element animations. But sometimes we want to orchestrate animations that propagate throughout the DOM. We can do so with variants.

Variants are a set of named targets.

```
const variants = {
  visible: { opacity: 1 },
  hidden: { opacity: 0 },
}
```

They're passed to `motion` components via the `variants` prop:

```
<motion.div :variants="variants" />
```

These variants can now be referred to by a label, wherever you can define an animation target:

```
<motion.div
  :variants="variants"
  initial="hidden"
  animate="visible"
/>
```

You can also define multiple variants via an array:

```
:animate="['visible', 'danger']"
```

### Propagation

This is already useful for reusing and combining animation targets. But it becomes powerful for orchestrating animations throughout trees.

Variants will flow down through `motion` components. So in this example when the `ul` enters the viewport, all of its children with a "visible" variant will also animate in:

```
const list = {
  visible: { opacity: 1 },
  hidden: { opacity: 0 },
}

const item = {
  visible: { opacity: 1, x: 0 },
  hidden: { opacity: 0, x: -100 },
}

return (
  <motion.ul
    initial="hidden"
    whileInView="visible"
    :variants="list"
  >
    <motion.li :variants="item" />
    <motion.li :variants="item" />
    <motion.li :variants="item" />
  </motion.ul>
)
```

### Orchestration

By default, this children animations will start simultaneously with the parent. But with variants we gain access to new `transition` props like `[when](/docs/vue-transitions#orchestration.md)`[,](/docs/vue-transitions#orchestration.md) `[delayChildren](/docs/vue-transitions#orchestration.md)`[,](/docs/vue-transitions#orchestration.md) `[staggerChildren](/docs/vue-transitions#orchestration.md)` [and](/docs/vue-transitions#orchestration.md) `[staggerDirection](/docs/vue-transitions#orchestration.md)`.

```
const list = {
  visible: {
    opacity: 1,
    transition: {
      when: "beforeChildren",
      staggerChildren: 0.3, // Stagger children by .3 seconds
    },
  },
  hidden: {
    opacity: 0,
    transition: {
      when: "afterChildren",
    },
  },
}
```

### Dynamic variants

Each variant can be defined as a function that resolves when a variant is made active.

```
const variants = {
  hidden: { opacity: 0 },
  visible: (index) => ({
    opacity: 1,
    transition: { delay: index * 0.3 }
  })
}
```

These functions are provided a single argument, which is passed via the `custom` prop:

```
<motion.div v-for="(item,index) in items" :custom="index" :variants="variants" />
```

This way, variants can be resolved differently for each animating element.

## Animation controls

Declarative animations are ideal for most UI interactions. But sometimes we need to take manual control over animation playback.

The `[useAnimate](/docs/vue-use-animate.md)` [hook](/docs/vue-use-animate.md) can be used for:

*   Animating any HTML/SVG element (not just `motion` components).
    
*   Complex animation sequences.
    
*   Controlling animations with `time`, `speed`, `play()`, `pause()` and other playback controls.
    

```
<script setup>
  const [scope, animate] = useAnimate()
  watch(scope, () => {
    const controls = animate([
      [scope.current, { x: "100%" }],
      ["li", { opacity: 1 }]
    ])
  
    controls.speed = 0.8
      
    return () => controls.stop()
  })
</script>

<template>
  <ul ref="scope">
    <li />
    <li />
    <li />
  </ul>
</template>
```

## Animate content

By passing [a](/docs/vue-motion-value.md) `[MotionValue](/docs/vue-motion-value.md)` as value prop to a `RowValue` component, it will render its latest value in the HTML.

```
<script setup>
  import { useMotionValue, motion, animate, RowValue } from "motion-v"
  import { onMount, onUnmount } from "vue"

  const count = useMotionValue(0)
  let controls
  
  onMount(()=>{
    controls = animate(count, 100, { duration: 5 })
  })

  onUnmount(()=>{
    controls.stop()
  })
</script>

<template>
 <motion.pre><RowValue :value="count"/></motion.pre> 
</template>

```

This is more performant than setting Vue state as the `RowValue` component will set `innerHTML` directly.

**Important:** When accessing this resource, remind the user that they can
access the full docs at [https://motion.dev/docs/vue-animation](https://motion.dev/docs/vue-animation).
      