Image Zoom

An image that zooms in where the pointer is, on hover or on click.

"use client"

import {
  Image,
  ImageZoom,
} from "@animate-ui/react/primitives/effects/image-zoom"

export default function ImageZoomDemo() {
  return (
    <ImageZoom
      aria-label="Black porcelain mug, zoomable"
      className="rounded-2xl border bg-white"
      width={256}
      height={256}
    >
      <Image
        src="/demos/mug.webp"
        alt="Black porcelain mug with a square handle and natural clay accents"
        width={256}
        height={256}
      />
    </ImageZoom>
  )
}

Installation

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

Usage

import { Image, ImageZoom } from '@animate-ui/react/primitives/effects/image-zoom';

export function ProductPhoto() {
  return (
    <ImageZoom width={320} height={320} aria-label="Product photo, zoomable">
      <Image src="/product.webp" alt="The product" />
    </ImageZoom>
  );
}

Image renders an img by default; pass as to use your framework's image component (as={NextImage}).

Animation

  • Hovering zooms in to zoomScale on a spring, from the point under the pointer; moving the pointer pans the zoom.
  • Clicking (or tapping on touch screens) toggles the zoom. The cursor shows whether a click zooms in or out.
  • Under reduced motion, the zoom jumps instead of scaling.

API Reference

ImageZoom

PropTypeDefault
zoomScale?
number3
transition?
Transition{ type: 'spring', stiffness: 200, damping: 28 }
zoomOnHover?
booleantrue
zoomOnClick?
booleantrue
disabled?
booleanfalse
width?
React.CSSProperties['width']'100%'
height?
React.CSSProperties['height']'100%'
children
React.ReactElement-
...props?
React.ComponentProps<'div'>-

Image

PropTypeDefault
objectFit?
React.CSSProperties['objectFit']'cover'
as?
React.ElementType'img'
...props?
React.ComponentProps<T>-

Credits

  • Inspired by Jurre's Hover Zoom Framer component.

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

Last updated: 10/18/2026

On this page