ThreeJS 3D Slider
What it does
A Three.js curved plane displays an endless vertical slideshow of captioned images drawn onto a repeating 2D canvas texture. Lenis smooth-scroll progress feeds a scroll listener that shifts the texture offset and re-renders the WebGL scene, so scrolling the tall page pushes the image strip through the 3D wave.
How it's built
| Category | 3d-webgl |
|---|---|
| Tech | three, lenis |
| Complexity | page |
| Performance cost | heavy |
| Mobile-safe | desktop-first |
| Scroll | hijacks scrolling |
How it works
A slideshow that runs over a 3D wave. The screen shows one tall sheet seen at an angle, and on it a column of captioned photographs that flows upwards as you scroll, curling towards you at the top and bottom of the frame like paper over a curved surface. It never ends: scroll on and the first slide comes round again.
It is built with Three.js and Lenis. There is no GSAP and, more unusually, no shader and no continuous render loop.
One plane, one canvas
The trick is that there is only one object in the scene. A large plane is subdivided into a fine grid, and its vertices are pushed towards the camera in proportion to the square of their distance from the vertical centre, so the sheet is flat in the middle and curves forward at both ends. The plane is tilted and seen from a camera placed off to one side and slightly rolled, which turns that curve into the flowing wave you see.
The slides are not separate meshes. They are all painted into a single tall 2D canvas, one below the other, each photograph cropped to fill its slot and its title drawn on top, and that canvas becomes the texture of the plane. Scrolling moves the slides inside the canvas rather than moving anything in 3D. The texture repeats vertically and the drawing wraps around the canvas height, with a couple of extra slides painted past each end, so the loop has no visible seam.
Scroll drives rendering
The page is made very tall so it has room to scroll, and that scroll distance is the only input. Lenis smooths it and reports a progress from top to bottom; on every scroll event the canvas is redrawn at the new offset, the texture is sent to the GPU and the scene is rendered once. When the page is still, nothing is drawn at all. That on-demand rendering is a good fit for a scene whose only motion comes from the reader.
Every photograph is also run through a duotone on the canvas, using blend modes to strip its colour and remap it onto the page's palette, so images from any source sit together as one set.
Where it gets hard
Matching colours across three places is the quiet pitfall: the page background, the WebGL clear colour and the canvas fill must be identical or the plane shows up as a rectangle on the page. The other is the wrap: the offset, the modulo and the overdraw have to agree exactly, or a gap flashes at the seam once per cycle.
Performance and mobile
Redrawing a large canvas and uploading it as a texture on every scroll event is the main cost, together with a densely subdivided plane. It is comfortable on desktop GPUs. For phones, a smaller canvas, fewer subdivisions and a capped pixel ratio help, and the tall scroll runway should be shortened so the slideshow does not dominate the page.
Rebuild it with AI
This component's prompt is part of the paid library. Below you can read how it starts; the full prompt, the exact structure, timing and easing an AI agent needs to rebuild the effect, unlocks with any paid plan, yearly or lifetime.
# ThreeJS 3D Curved Slider (WebGL canvas-texture, Lenis scroll, no GSAP)
## Goal
Build a full-screen **3D curved plane that displays an endless vertical slideshow of captioned images**, rendered entirely in Three.js. Seven images with title captions are painted onto a tall repeating **2D canvas** that is used as a texture on one big **parabolically curved plane** tilted in 3D space. **Lenis smooth-scroll progress (0→1 over a very tall page) is fed into a scroll listener that shifts the texture's vertical offset and re-renders the WebGL scene**, so scrolling pushes the strip of images continuously up through the curved 3D sheet and loops forever. The star effect: the **image strip appears to bend and flow over a concave wave** because the flat canvas is mapped onto a plane whose vertices curve toward the camera at the top and bottom edges, viewed from an angled, rolled camera. A dark radial vignette overlay and fixed nav/footer frame the scene.
## Tech
- Vanilla HTML / CSS / JS with ES module imports, bundled by **Vite** (npm project).
- **`three` (npm)** imported `import * as THREE from "three";` and **`lenis` (npm)** imported `import Lenis from "lenis";`.
- **No GSAP, no ScrollTrigger, no shaders.** All motion is: Lenis for smooth scroll + a `lenis.on("scroll", …)` callback that redraws a 2D `<canvas>` texture and calls `renderer.render()`. There is **no continuous rAF render loop** — the scene renders once at init and then only on scroll events. `MeshBasicMaterial` (unlit) — no lights.
- Everything runs inside a single `window.addEventListener("load", …)` in one `script.js`.
## Layout / HTML
Almost no DOM — a fixed nav, a fixed footer, the WebGL `<canvas>` inside a wrapper, and a vignette overlay. Text is neutral/fictional demo copy (no real brands). Class names are load-bearing (`.slider-wrapper`, `.overlay`).
```html
<nav>
…
Premium prompt
Unlock this prompt, and every other one
From $99/year, or $139 once for lifetime access. Commercial license included.
See pricing Or start with the free set Already bought? Sign in
Learn the technique
New components in your inbox
One email a week, only when new components ship, each with its live demo and prompt.