Pixel Smear Carousel

ProShowcase & MediaWebGLpowered by @vectorvesper/motion

A carousel whose slides smear into one another through the transition, with autoplay, interval control, and an optional text overlay layer above the imagery.

Pixel Smear Carousel

Included with membership

Members install Pixel Smear Carousel with one command and get the full source, the usage code and the Framer remix, licensed for client work. One membership covers the whole library and the CLI.

When to use it

A small, curated set of images where moving between them should feel physical — a project index, a lookbook, a launch. The smear tracks drag velocity, so it rewards being dragged rather than clicked through; it is the wrong shape for a gallery someone needs to scan quickly.

  • Give the wrapper a height — the canvas fills its container and an unsized container renders nothing.
  • Turn on showTextOverlay if you are passing title and subtitle; without it they are ignored, which reads as the props not working.
  • Use landscape images of similar proportion. The slides share one surface, so a portrait among landscapes letterboxes oddly.
  • Keep the set small. Every slide is uploaded as its own texture at mount.

Avoid:

  • Do not turn on autoplay for a set someone is meant to read — the smear fires on every advance and pulls the eye back each time.
  • Do not give two slides the same id; it keys the textures and duplicates collide.
  • Do not lower interval to a second or two with autoplay on. The transition never settles and the component looks like it is glitching.

Props

A carousel where slides do not slide — they smear into each other, the outgoing image dragging across the frame in streaks before the next one resolves.

<PixelSmearCarousel />

The carousel. Fills its container, so give the parent a height.

PropTypeDefaultDescription
slides*CarouselSlide[]—The slides, in order. Required.
autoplaybooleanfalseAdvances on its own. Off by default — turn it on deliberately, since it is continuous motion the visitor did not ask for.
intervalnumber5000Milliseconds each slide holds before advancing, when autoplay is on.
showTextOverlaybooleanfalseDraws each slide's title and subtitle over the image. Off by default, so the titles you pass are not shown unless you ask for them.
classNamestring""Applied to the wrapper.
dprnumberthe screen'sPixel ratio the slides are drawn at, before the quality tier scales it.
disableAdaptiveQualitybooleanfalseDraws at full resolution on every device. By default the canvas is scaled to 0.85 on a mid tier and 0.7 on the most constrained one; set this and the tier is ignored.
mount"auto" | "eager""eager"When to build the smear. The default builds it on mount. Set "auto" to wait until the carousel is near the viewport and the page has frame headroom. The current slide is a plain image underneath, so a deferred build still shows the right picture throughout — only the smear between slides waits. Neither setting takes it off the shared frame loop or overrides the reduced-motion preference. A scene running its own loop would be invisible to the scheduler, so it could not be set aside under load, and it would slow every other animation on the page rather than only itself.

<CarouselSlide />

type

One slide.

PropTypeDefaultDescription
id*string—Stable key for the slide.
src*string—The image.
titlestring—Headline, shown only when showTextOverlay is on.
subtitlestring—Supporting line, same condition.
The smear runs on every transition with no reduced-motion guard. Leave autoplay off when the preference is set, so the motion only happens when the visitor asks for it.
The smear samples the outgoing image many times per frame while it runs. Ship the slides near the size they are shown at — a full-resolution photo is the expensive part.
Client component. It opens a GPU drawing context on mount — import it dynamically with ssr: false if your route renders on the server.
It draws on the shared frame loop rather than starting one of its own, so putting several animated components on a page costs one callback, not one each, and the scheduler can set decorative work aside when frames get tight. If the browser takes the drawing context away — which it does under memory pressure, and more often on a page with several of these — the component reports it and rebuilds once the context comes back, instead of leaving a permanently black rectangle.
Back to all components