GSAP Scroll Dial Services Index with WebGL Glass Arch
Overview
A pinned services index on a dial shaped like the letter C: each scroll clicks it on exactly one entry, the copy rebuilds itself, and the entry's photo rises through an arched window of fluted glass drawn in three.js.
One section of a normal page. It pins once its top reaches the top of the screen, and its entries sit on a dial that curves away like the letter C: the word at the centre is fully lit, the rest fade round the curve, with a hairline ring, ticks and a gold progress arc drawn alongside. Scrolling turns the dial, and the right side shows that entry: its heading rises letter by letter from masks, the text line by line, the label decodes and the list slides in.
Details
- Category
- Scroll
- Interaction
- On Scroll + On Hover + Mouse Move + On Click
- Trigger
- On Scroll
- Languages
- React, TypeScript, Tailwind
(01)Keep exploring
All 24 componentsBuilt with the same techniques
No. 019 / Scroll
GSAP Pinned Service Cards with Animated Reveals
On Scroll · On Hover · Mouse Move · On Click
No. 018 / Scroll
GSAP WebGL Knockout Dive & Aperture Scroll Section
On Scroll · On Load · Mouse Move · On Hover
No. 021 / Scroll
GSAP Pinned Statement Hero with Expanding Photo
On Load · On Scroll
(02)FAQ
GSAP Scroll Dial Services Index with WebGL Glass Arch — FAQ
01What do I need to install?
npm install gsap @gsap/react three, plus lenis if you keep the optional smooth scroll. SplitText, ScrambleText and ScrollTrigger come with gsap. It's built for Next.js (it uses next/image) with Tailwind CSS v4.
02How do I add my own entries?
Pass an items array: the title for the dial (one or two words read best), a heading, the text, an optional list of points, a photo (around 1400px wide is plenty), an optional focus point to keep in view when the window crops it, and a colour for its swatch, the glow behind the dial and the tint in the photo's shadows.
03How many entries can it take?
As many as you like. Each adds three quarters of a screen of scroll (scroll.perItem in config.ts); six to eight read best on the dial.
04Can I put other sections above and below it?
Yes, that's how it's meant to be used. It pins when its top reaches the top of the screen and releases after the last entry.
05Does it work with Lenis?
Yes. Render the SmoothScroll that comes with it once on the page. If your page runs its own Lenis, connect it with lenis.on("scroll", ScrollTrigger.update) and call setSmoothScroll(lenis) from scroll.ts, so the dial's glides run through it. The one-entry-per-scroll wheel works with or without Lenis.
06What happens without WebGL?
On a computer without hardware graphics, or in a browser with hardware acceleration turned off, it skips three.js and does the same in CSS: the next photo rises through the arch with a line of light along it, and the pointer carries a loupe of fluted glass over the photo.
07Which fonts does it use?
The dial and the headings are set in Instrument Serif and the labels in Geist Mono: load them with next/font as the --font-instrument-serif and --font-geist-mono variables (they fall back to Georgia and your system monospace). The text uses your page's sans.
08How do I tune the motion?
Every value is in config.ts: the colours, the dial's spacing and radius, the scroll per entry, how far a scroll must go and how long the wheel must rest before it counts as a new one, the Lenis smoothing, the flute width and how long the photo change takes.