Zoom

An entrance that scales elements up into place on load or when they scroll into view.

<script setup lang="ts">
import { RepeatIcon } from '@hugeicons/core-free-icons'
import { HugeiconsIcon } from '@hugeicons/vue'
import { Zooms } from '@animate-ui/vue/primitives/effects/zoom'
import { ref } from 'vue'
import { Button } from '@/components/ui/button'

withDefaults(
  defineProps<{
    delay?: number | string,
    initialScale?: number | string,
    scale?: number | string
  }>(),
  { delay: 0, initialScale: 0.5, scale: 1 },
)

const ITEMS = ['Design', 'Build', 'Ship']
const run = ref(0)
</script>

<template>
  <div class="flex flex-col items-center gap-6">
    <div :key="`${run}-${delay}-${initialScale}-${scale}`" class="flex gap-3">
      <Zooms
        :hold-delay="100"
          :delay="Number(delay)"
          :initial-scale="Number(initialScale)"
          :scale="Number(scale)"
      >
        <div
          v-for="item in ITEMS"
          :key="item"
          class="flex h-20 w-24 items-center justify-center rounded-xl bg-accent text-sm font-medium"
        >
          {{ item }}
        </div>
      </Zooms>
    </div>
    <Button variant="outline" size="sm" @click="run++">
      <HugeiconsIcon :icon="RepeatIcon" :stroke-width="2" />
      Replay
    </Button>
  </div>
</template>

Installation

npm install @animate-ui/vue motion-v
pnpm add @animate-ui/vue motion-v
yarn add @animate-ui/vue motion-v
bun add @animate-ui/vue motion-v

Usage

<script setup lang="ts">
import { Zoom, Zooms } from '@animate-ui/vue/primitives/effects/zoom';
import Card from './Card.vue';
</script>

<template>
  <Zoom>
    <h1>Animated primitives for Vue</h1>
  </Zoom>
  <!-- Staggered: each child starts 100ms after the previous one. -->
  <Zooms :hold-delay="100">
    <Card />
    <Card />
    <Card />
  </Zooms>
</template>

With as-child, the animation is applied to your element instead of a wrapping div.

Animation

  • The element scales from initial-scale (0.5 by default) to scale on a spring (stiffness 200, damping 20), overshooting by about 2% before it settles.
  • Under reduced motion, it doesn't scale: it fades in instead.
  • in-view waits for the element to scroll into view, once by default.
  • <AnimateUIProvider :tempo> paces the default spring.

API Reference

Zoom

PropTypeDefault
as-child?
booleanfalse
initial-scale?
number0.5
scale?
number1
delay?
number0
transition?
Transition{ type: 'spring', stiffness: 200, damping: 20 }
in-view?
booleanfalse
in-view-once?
booleantrue
in-view-margin?
string'0px'
...props?
HTMLMotionProps<'div'>-

Zooms

Wraps each child in a Zoom, delaying each one a little more than the previous.

PropTypeDefault
#default
slot-
hold-delay?
number0
...props?
ZoomProps-

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/23/2026