Image Trail Component
A cursor-driven effect that spawns a trail of images as the pointer moves across a scoped area — the editorial, portfolio-site look, built to stay out of the way of your interactive UI.
Features
- Scoped to its own container — nothing spawns outside it, and the trail layer is
pointer-events: none, so links and buttons underneath stay fully clickable. - Distance-based spawning: a still cursor emits nothing, fast movement reads as a trail.
- Suppresses over interactive elements via a configurable
ignoreSelector. - Five appearance styles —
scale,fade,blur,rise, andtilt. - Fixed image budget (
maxImages) with automatic recycling — no unbounded DOM growth. - Respects
prefers-reduced-motionand only runs for a fine (mouse) pointer.
Move your cursor here
Interactive content underneath
The trail layer is pointer-events: none, so images can visually sit on top of buttons and links without ever intercepting clicks or hover. The effect also skips spawning while the cursor is over anything matching ignoreSelector (default a, button, input, [data-image-trail-ignore]), keeping interactive UI unobstructed. Sweep across the area below, then click the button or hover the link.
Sweep the cursor to spawn the trail, then click the button or the link — the images never block them.
A link that stays hoverableVariants
Each appearance style has its own enter/exit motion. Set it via the variant prop.
Blur
Blur trail
Tilt
Tilt trail
Playground
Change the appearance style, spawn distance, image budget, and lifetime, then move your cursor across the area.
Installation
Usage
Props
| Property | Type | Default | Description |
|---|---|---|---|
images | string[] | required | Image sources spawned in order as the pointer moves. |
children | ReactNode | required | The content the effect is scoped to; the trail only spawns over this area. |
className | string | — | Additional CSS classes for the container. |
itemClassName | string | "w-40" | Extra classes for each trail image (use for sizing, e.g. `"w-48"`). |
threshold | number | 80 | Pointer distance in pixels travelled before the next image spawns. |
maxImages | number | 8 | Maximum number of images alive at once. |
lifetime | number | 600 | How long an image stays before it animates out, in milliseconds. |
variant | "scale" | "fade" | "blur" | "rise" | "tilt" | "scale" | Entrance and exit animation style. |
ignoreSelector | string | "a, button, input, [data-image-trail-ignore]" | CSS selector for elements that suppress the effect when hovered, keeping interactive UI unobstructed. |
zIndex | number | 10 | z-index of the trail layer. |