Build a 3D CMS Cube Gallery on Scroll in Webflow

Advanced 50:22 webflowgsapcms3dscroll

Build a scroll-driven 3D cube gallery in Webflow from CMS data — cross-fading images, split text, and a cube rotating through space with 3D transforms and GSAP.

Key takeaways

  • A tall section (e.g. 500vh) plus a sticky, full-viewport container turns scroll distance into animation time — the container is a fixed "window" while the page scrolls past behind it.
  • Store each cube face's transform in the CMS — origin, move X/Y/Z, rotate X/Y/Z as numeric fields — and bind them to each item's transform, so a six-item collection becomes the six faces of a cube.
  • This is a scrubbed animation: use scrub on scroll (not trigger actions) so the cube's rotation and the image transitions track scroll position directly.
  • A real 3D cube needs perspective on the container and transform-style: preserve-3d on the cube, so the faces rotate through space instead of flattening.
  • Rotate fields are integers and move fields decimals for a reason — precision matters when positioning faces in 3D, and tiny differences read as misaligned faces.

Video chapters

  1. 00:00 Intro
  2. 01:06 Breaking down the CMS collection structure
  3. 05:30 Structure for the image & split-text transition
  4. 13:16 First scroll animation: image & split-text transition
  5. 30:07 Building the CMS-powered 3D cube
  6. 40:35 Second scroll animation: cube rotation & movement
  7. 47:22 Final refinements & responsive adjustments
  8. 49:17 Outro

This is the most ambitious build in the series: a fully CMS-powered cubic gallery where images cross-fade into one another while a real 3D cube rotates and travels through space as you scroll. It looks like something Webflow “can’t do” — and it comes together from pieces you already know: a scrubbed scroll interaction, CMS-driven transforms, split text, and a little 3D CSS.

Because it’s a big one, this companion focuses on the mental model — the four ideas that make it work — rather than every click. Pair it with the cloneable and the Codrops write-up to build along.

How it works

Scroll distance becomes animation time. The section is deliberately tall (500vh — an arbitrary value that sets the overall speed; taller = slower). Inside it, a full-viewport container is position: sticky; top: 0, so it pins in place and acts as a fixed window while the rest of the section scrolls past. A scrubbed GSAP scroll interaction maps how far you’ve scrolled through the section onto the animation’s progress. This is scrub-on-scroll, not trigger actions: the cube rotates and the images cross-fade as you scroll, forward or backward.

The cube is built from the CMS. The clever part is that each face’s position is data. The pictures collection has the obvious fields (image, a short text for the split-text label, an order integer capped at 6 — because a cube has six faces) plus eight “mysterious” numeric fields: origin-left, origin-top, move-x/y/z, and rotate-x/y/z. Those map exactly to CSS transform-origin and the move/rotate transforms. Bind each item’s transform to its own fields (via custom CSS driven by the item’s data) and the six collection items arrange themselves into a cube — each face rotated and pushed out along an axis. Note the field types: rotate values are integers, move values are decimals, because positioning faces in 3D needs that precision — small errors read as visibly misaligned faces.

Two collection lists, two jobs. One collection list renders the background images (stacked on top of each other, sorted by order descending so item 1 sits on top at the start) for the cross-fade + split-text transition. A second uses the same data to build the cube faces. Splitting the work keeps each animation focused.

Real 3D needs two CSS properties. A CSS “cube” looks flat unless the scene has depth: set a perspective on the parent (how strong the 3D foreshortening is) and transform-style: preserve-3d on the cube element, so its faces keep their individual 3D positions instead of being flattened onto the parent’s plane. With those in place, the rotate/move transforms actually move faces through space.

How to use it

  1. CMS. A pictures collection with image, a short text, an integer order (max 6), and eight numeric fields: origin-left, origin-top, move-x, move-y, move-z, rotate-x, rotate-y, rotate-z (rotates integer, moves decimal).

  2. Scroll scaffold. Section at 500vh. Inside, a main-container at 100vh, position: sticky, top: 0, max-width: none — the pinned window. Inside that, a content wrapper at 100%×100%.

  3. Two lists. A background collection list (images stacked, sorted by order descending) for the image + split-text transition, and a second collection list for the cube faces. Bind each cube item’s transform-origin and move/rotate transforms to its CMS fields via custom CSS (from the cloneable). Add perspective to the cube’s parent and transform-style: preserve-3d to the cube.

  4. First animation — image & split text. A scrubbed scroll interaction that cross-fades the stacked images and runs a split-text stagger on each text as scroll progresses.

  5. Second animation — cube. A scrubbed scroll interaction that animates the cube’s rotation and position through the scene, synced to the same scroll. Finish with responsive adjustments for smaller screens.

The custom CSS that binds the CMS numeric fields to each item’s transform (and the exact face values) lives in the cloneable, with a full written breakdown in the linked Codrops article. Build the 3D math from those rather than reconstructing it by hand.

Resources

Frequently asked questions

How do I make a scroll animation play as I scroll through a Webflow section?
Give the section a tall height (e.g. 500vh) so there's scroll distance to work with, and make an inner full-viewport container position: sticky with top: 0 so it stays pinned as a "window". A scrubbed GSAP scroll interaction then maps the scroll position within that section to the animation's progress.
How can I build a 3D cube from a CMS collection?
Add numeric fields to the collection for each face's transform — transform origin, move X/Y/Z, rotate X/Y/Z — and bind them to each collection item's transform via custom CSS. Six items become the six faces: each one is rotated and pushed out along an axis to form the cube.
What's the difference between scrub on scroll and trigger actions?
Scrub on scroll ties the animation's playhead directly to scroll position, so scrolling scrubs the timeline back and forth — right for a cube that should rotate as you scroll. Trigger actions instead fire an animation once at a threshold and let it play on its own.
Why does my CSS 3D cube look flat in Webflow?
Two properties are usually missing: a perspective value on the parent (which gives depth to the scene) and transform-style: preserve-3d on the cube element (so its children keep their 3D positions instead of being flattened into the parent's plane).

← Back to the course