Zoom Lens
An image magnifier whose lens follows the cursor and magnifies in place, or presents the magnified result in a side panel.
Loading preview…
npx shadcn@latest add https://webberui.com/r/zoom-lens.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
2.5
160
<ZoomLens />
Installation
npx shadcn@latest add https://webberui.com/r/zoom-lens.jsonOr, once registries are configured in components.json, install it as @webberui/zoom-lens.
Usage
import { ZoomLens } from "@/components/ui/zoom-lens";
<ZoomLens
src="/product.jpg"
alt="Product detail shot"
className="w-full max-w-md"
/>Side panel mode
The panel variant marks a viewfinder box on the original image and shows the magnified result in a side panel — a good fit for e-commerce product images.
<ZoomLens
src="/product.jpg"
alt="Product detail shot"
variant="panel"
panelPosition="right"
zoom={2.6}
size={200}
className="w-64"
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image source URL |
alt | string | "" | Alternative text for the image |
variant | "lens" | "panel" | "lens" | How the magnification is presented |
zoom | number | 2.5 | Magnification factor |
size | number | 160 | Lens diameter (lens) / panel edge length (panel), in px |
shape | "circle" | "square" | "circle" | Lens shape (lens only) |
panelPosition | "right" | "left" | "top" | "bottom" | "right" | Panel position (panel only) |
disabled | boolean | false | Disable the magnification interaction and show only the original image |
onZoomChange | (active: boolean) => void | — | Callback when the magnification on/off state changes |
className | string | — | className for the image frame; set the image size here |
imageClassName | string | — | className for the <img> |
How it works
- Give a width in
className(such asw-full max-w-md) and the image expands at its natural ratio withh-auto; the component measures the displayed size through aResizeObserverand computes the magnified background from it. - The viewfinder's center is clamped inside the image's bounds, so the magnified content never exposes a blank edge.
- The position follows smoothly via a Motion spring;
lensandpanelshare the same background coordinate math, so the factor and size behave identically. - Mouse, touch, and stylus are all supported (Pointer Events); on touch you move the viewfinder by dragging, and it retracts when you let go.
Accessibility
- The
<img>keeps itsalt, and the magnification interaction is progressive enhancement, so assistive technology still announces the image normally. - The lens, the viewfinder box, and the magnification panel are all decorative layers marked
aria-hidden, so they do not interfere with the reading order. - When the user has "reduce motion" enabled at the system level, the tracking and the fade in/out land instantly, without using a spring or scaling.
- The component cleans up its
ResizeObserver, so no listeners are left behind on unmount.