@vectorvesper/motion/reactReact · Image Trail

useImageTrail

Appending an element per pointer move allocates dozens of DOM nodes a second, which shows up as garbage collection spikes and layout jitter once the pointer moves quickly. useImageTrail keeps a fixed pool of elements and recycles them, animated through the Web Animations API on the compositor thread.

The useImageTrail hook attaches to a bounded container to create a recycled image trail along the cursor's trajectory.

The hook creates a fixed pool of maxActive DOM image elements once upon mount. When the pointer travels the configured distance threshold (spacing), the next image in the pool is reused and animated.

Flights are executed via the browser's native Web Animations API (WAAPI) on compositor layers (transform and opacity). This provides 120 FPS performance with zero garbage collection overhead and zero CPU frame loops between movements.

Pooled Compositor Image Flights

WAAPI COMPOSITOR POOL
Demo loads on scroll

Quick start

Attach the returned ref to a container element with relative positioning and supply your image source array.

All trail images are marked aria-hidden and pointer-events: none, ensuring zero interference with underlying UI links.

DOM Node Pooling & WAAPI Execution

How memory pooling and browser compositor execution eliminate performance bottlenecks during continuous pointer motion.

1. Pre-Allocated DOM Ring Buffer

Rather than appending and removing elements per spawn, the hook allocates maxActive image elements once during mount. When the cursor travels spacing pixels, the oldest active animation is cancelled and its DOM element is repositioned to the current cursor coordinate.

2. Hardware-Accelerated Keyframe Flights

Keyframes are dispatched directly to element.animate() using GPU-accelerated translate(), scale(), and opacity. The main thread remains completely idle during flights.

API Reference

Syntax

Binds a container element to a cursor-following image trail powered by pooled DOM nodes and WAAPI.

Parameters

Parameters.fieldTypeDefaultDescription
options.imagesstring[](none)Array of image URLs cycled in sequential order.
options.sizenumber160Rendered width in pixels for each trail image.
options.spacingnumber90Cursor travel distance in pixels required to spawn the next image.
options.durationnumber900Lifespan in milliseconds for each image flight animation.
options.maxActivenumber10Maximum number of simultaneous active images in the pre-allocated pool.

Return Value

{ ref: RefObject<T | null> }

Ref attached to the bounding container element.

Properties & State

Properties.fieldTypeDescription
refRefObject<T | null>DOM ref attached to the trail container.

DOM Node Teardown & Pointer Unbinding

On unmount, all pre-allocated image elements and pointer event listeners are removed cleanly.

1. Automatic TeardownReact Hook Lifecycle
2. Remounting for Dynamic Option ChangesKey-Based Re-initialization

Lifecycle & Invariant Guarantees

  • Zero GC allocation during movement: Recycles a pre-allocated array of DOM elements, eliminating memory allocation spikes during active mouse movement.
  • Compositor execution: Dispatches animations to the browser Web Animations API, running transforms entirely on GPU compositor threads.
  • Complete accessibility safety: Trail elements carry aria-hidden='true', empty alt attributes, and pointer-events: none, ensuring zero interference with screen readers.
  • Touch and reduced-motion safety: Automatically disables itself on touch devices and when prefers-reduced-motion is active.

Production Examples

Battle-tested production patterns ready to copy directly into your codebase.

Full-bleed hero banner with generous image size and spacing for visual impact.

When NOT to use this

Essential navigation links or core UI browse interactions.
→ instead Build a standard interactive gallery. Image trail particles are decorative enhancements that do not respond to clicks.
High-density data tables or utility dashboards.
→ instead Keep data views clear. Trails compete with dense information for user attention.
Loading dozens of uncompressed full-resolution photographs.
→ instead Downsample and compress trail images to thumbnail resolutions (under 50KB each) to preserve network bandwidth.

Rules & Gotchas

  • Curate optimized thumbnail assets: Compress image sources to their rendered display dimensions (e.g. 160px width) rather than loading raw camera photos.
  • Tune spacing before pool size: Increasing spacing distance creates more deliberate, legible visual flights than crowding high numbers of images.
  • Treat the trail as purely visual decoration: Ensure underlying text and navigation elements remain completely functional without requiring the trail.
  • Use keys to retune options dynamically: Options are read once upon mount to construct the DOM pool; update the React key when changing configurations.

Related Motion Components