webdevpuneet.com

Scroll Rotate Gallery — Free GSAP 3D Carousel Scroll Snippet

Scroll Rotate Gallery · Scroll · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<section class="rt-top"><p>Scroll ↓</p></section>
<section class="rt-stage" id="rtStage">
  <div class="rt-ring" id="rtRing">
    <figure class="rt-card" style="--i:0;--g:linear-gradient(160deg,#6366f1,#22d3ee)"></figure>
    <figure class="rt-card" style="--i:1;--g:linear-gradient(160deg,#a855f7,#ec4899)"></figure>
    <figure class="rt-card" style="--i:2;--g:linear-gradient(160deg,#10b981,#84cc16)"></figure>
    <figure class="rt-card" style="--i:3;--g:linear-gradient(160deg,#f59e0b,#ef4444)"></figure>
    <figure class="rt-card" style="--i:4;--g:linear-gradient(160deg,#0ea5e9,#6366f1)"></figure>
    <figure class="rt-card" style="--i:5;--g:linear-gradient(160deg,#f43f5e,#f59e0b)"></figure>
  </div>
</section>
<section class="rt-bottom"><p>The carousel turned with your scroll.</p></section>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

CSS 3D cylinder
rotateY + translateZ arrange the ring.
Parent spin
Rotating the ring turns all cards.
Pinned + scrubbed
Spin tracks the scrollbar.
Momentum
scrub 1 gives the turn weight.
Idle bob
Looping yoyo keeps it alive.
Composed transforms
y and rotateY animate together.
Hidden backfaces
backface-visibility cleans the far side.
GPU 3D
Transforms only, no reflow.

About this UI Snippet

Scroll Rotate Gallery — A 3D Carousel Driven by Scroll

Screenshot of the Scroll Rotate Gallery snippet rendered live

The scroll rotate gallery is a 3D cylinder of cards arranged in a ring that spins as you scroll, like a carousel turning under your control — an eye-catching way to present a set of images or features. This snippet builds it with GSAP and ScrollTrigger (from a CDN) and pure CSS 3D, no carousel library.

Arranging cards in a cylinder

Each card is positioned with CSS: transform: rotateY(i × 60deg) translateZ(230px). The rotateY fans the six cards evenly around a circle (360° ÷ 6 = 60° each), and the translateZ pushes each out from the center by the cylinder's radius — so they form a ring facing outward. The stage provides perspective and the ring uses transform-style: preserve-3d so the depth renders correctly. This is the classic CSS 3D carousel construction, done entirely with two transforms per card.

Scroll spins the ring

A single tween rotates the whole .rt-ring on its y-axis as the section is pinned and scrubbed over end: '+=200%'. Because the cards are children of the ring, rotating the parent turns the entire cylinder — the cards sweep toward and away from the viewer in sequence. scrub: 1 adds a touch of momentum so the spin feels weighty, and the pin holds the stage so the rotation plays over a controlled scroll distance.

Why rotate the parent, not the cards

Spinning the single ring container is far cheaper and simpler than re-rotating six cards every frame, and it keeps their relative arrangement locked — they stay a rigid cylinder while it turns. The cards' own transforms are set once on load and never change; only the parent's rotateY animates.

A subtle idle bob

An independent, infinitely repeating yoyo tween floats the ring up and down a few pixels with a sine ease, so even when you stop scrolling the carousel feels alive rather than frozen. Because it animates y on the same element while the ScrollTrigger animates rotateY, GSAP composes the two transforms without conflict.

Composited 3D

Everything animates transforms (rotateY, y), so the browser composites on the GPU with no reflow, and backface-visibility: hidden hides the reversed back faces of cards facing away. will-change: transform promotes the ring for a smooth spin.

Customizing it

Change the card count (update the 60deg to 360 ÷ count and the rotate distance), the radius (translateZ), the perspective for more or less drama, or swap gradients for real images. Pair it with a coverflow carousel, scroll perspective cards, or a scroll gallery pin.

Step by step

How to Use

  1. 1
    Add the GSAP CDNsInclude gsap and ScrollTrigger from the CDN panel.
  2. 2
    Paste HTML, CSS, and JSSix cards form a 3D cylinder.
  3. 3
    Scroll downThe carousel rotates through the section.
  4. 4
    PauseA gentle bob keeps the ring alive.
  5. 5
    Scroll back upThe ring spins backward — it is scrubbed.
  6. 6
    Change the countUpdate the per-card angle and radius.

Real-world uses

Common Use Cases

Showcase carousels
Present a ring of cards that spins as the user scrolls, as a scroll-controlled cousin of a coverflow carousel.
Pinned image galleries
Pair with a scroll gallery pin so one section scrolls sideways and another rotates in depth.
Feature reels
Rotate through feature cards arranged on a CSS cylinder using rotateY and translateZ, with scrub 1 giving the turn weight.
Tunnel and depth combinations
Combine with scroll perspective cards for a page with both a ring and a tunnel of content.
Product and brand moments
Turn a ring of product card shots, or open with a scroll zoom hero before the cylinder appears.
Related: Scroll Velocity Motion Blur
See the Scroll Velocity Motion Blur for a related scroll pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Each card uses transform: rotateY(i × 60deg) translateZ(230px). The rotateY fans the six cards evenly around a circle (360 divided by 6 is 60 degrees each) and the translateZ pushes each outward by the cylinder radius, so they face outward in a ring. The stage adds perspective and the ring uses preserve-3d so the depth renders.

Spinning the single ring container turns the whole cylinder at once, which is far cheaper than re-rotating six cards every frame and keeps their arrangement rigid. The cards' own transforms are set once on load and never change; only the parent's rotateY animates with scroll, so the cards sweep past the viewer in order.

An independent repeating yoyo tween animates the ring's y by a few pixels with a sine ease, while the ScrollTrigger animates the ring's rotateY. GSAP composes both transforms on the same element without conflict, so the carousel keeps a gentle float even when you stop scrolling, rather than freezing.

Yes. Everything animates transforms — rotateY and y — so the browser composites on the GPU with no layout reflow, backface-visibility: hidden removes the reversed back faces, and will-change promotes the ring. Because only the parent animates, adding more cards does not add per-frame animation cost.

Render the cards with their --i index, keep the cylinder transforms in CSS, and in a mount effect register ScrollTrigger and create the pinned rotateY tween plus the looping bob, scoped to a ref. Return a cleanup that reverts the GSAP context so the pin and the infinite tween stop on unmount. Update the per-card angle if you change the count.