# Spatial Product Range

> A product-first range selector with generated speaker cutouts, a seamless spatial carousel and complete fallback product cards.

Canonical: https://gsapvault.com/sections/spatial-product-range-section
Live demo: https://gsapvault.com/demos/spatial-product-range-section/index.html

| Property | Value |
|----------|-------|
| Type | section |
| Tier | paid |
| Price | Included only in the Vault |
| Difficulty | advanced |
| Plugins | Core GSAP only |
| Techniques | webgl-shader, pointer-drag, momentum, snap, keyboard-navigation, responsive-layout |
| Uses Lenis | No |

## Lighthouse, as measured

Google Lighthouse on the demo, 15 September 2026. A measurement of the demo as shipped, not a promise for your page.

| Category | Score |
|----------|-------|
| Accessibility | 100 |
| Best practices | 100 |

No performance score is published: it depends on the deployment (server compression, caching, CDN, connection and device) rather than on the code, so measure it where it will live.

## Overview

A complete ecommerce range selector for launches and collection pages. The worked example presents four sculptural desktop speakers with a clear proposition, large product stage, active name, price, finish, defining feature, model link and navigation arrows together in a compact stage footer.

Generated transparent product images form a spatial shelf: one model stays centred and readable while its neighbours recede along a shallow arc. Drag or swipe with momentum, use the visible arrows, or browse with the keyboard. Each selection brings the matching product details into view.

The section preserves normal page scrolling and pauses its rendering while out of view. Every product remains described and linked in a scrollable card layout when JavaScript, Three.js or WebGL is unavailable, and for visitors who prefer reduced motion.

## Features

- Complete product-range hierarchy with proposition, stage, price, defining feature, finish and model-specific CTA
- Four generated speaker cutouts shared by the spatial stage and semantic fallback cards
- Centred readable product with symmetric neighbours receding on a real perspective arc
- Pointer drag and touch swipe with projected release momentum and frame-rate-independent spring snap
- Visible previous and next controls, programmatic selection and ArrowLeft or ArrowRight keyboard control
- Designed mobile WebGL composition with capped pixel ratio and touch-friendly drag
- Four-card semantic scroll-snap fallback for no JavaScript, missing dependencies, failed WebGL and reduced motion
- Root-scoped tokens, container-aware layout, independent instances and complete GPU teardown

## Use Cases

- Consumer electronics range and launch pages
- Furniture, lighting and homeware collections
- Coffee equipment and countertop appliance families
- Footwear or accessories presented as a tight model range

## Vibe-Code Ready Setup

This website section includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

The selected product sits at the front of a curved Three.js display, with neighbouring models visible on either side. Dragging follows the pointer or finger, then settles on a model when released. Arrow buttons and keyboard controls offer the same browsing choices, and repeated input smoothly changes the destination.

The active name, price, finish and product link update together with a restrained GSAP transition. The composition adapts to its available space, and multiple sections can operate independently on one page.

Visitors using reduced motion receive complete product cards with ordinary links. The same fallback remains available if the enhanced display cannot load. Removing a section releases its animation and graphics resources without affecting the host page.

## Documentation

How this website section works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

**1. Add the stylesheet and WebGL probe to your `<head>`:**

_Code snippet omitted: it ships with the download._

The inline probe is required. It hides the fallback before first paint only
when WebGL and normal motion are available. If Three.js, GSAP or the renderer
later fails, the section removes `html.gl` and the complete product-card range
returns. This prevents a flash of cards while the module is loading without
turning failure into a blank section.

**2. Copy the complete section from `index.html`:**

_Code snippet omitted: it ships with the download._

The example is tuned for four products. Keep every product's visible fallback
article: the script reads those records, and the articles are the actual
experience under reduced motion or a missing dependency.

**3. Load GSAP, Three.js and the section script before `</body>`:**

_Code snippet omitted: it ships with the download._

Three.js is loaded as an ES module because its old UMD build is deprecated.
The short shim deliberately puts the module on `window` before appending the
classic section script, which keeps that script usable without a build step.
Its error path removes the preflight gate, so a blocked CDN restores the
fallback instead of leaving a hidden source list.

Already importing Three in your application? Skip the import map and set
`window.THREE = THREE` before `assets/script.js` executes.

### Using It With Your Own Design

**Required markup:** one `[data-spatial-range]` root, one `[data-spr-source]`
wrapper containing two or more `[data-spr-model]` articles, and the enhanced
stage/footer block shown in `index.html`. The script queries only
`data-spr-*` hooks; presentation classes can change if you update the CSS.

**Keep the fallback complete.** Each product article needs its own name, price,
defining feature, finish and real CTA link in visible HTML. Do not replace it
with hidden data or an empty loading message. That card range is how the
section still performs its sales task with no JavaScript, no WebGL, a blocked
CDN or reduced motion.

**CSS the mechanism depends on:**

- `.spr-stage` needs a real height and `position: relative`; the renderer sizes
  itself from this element with a `ResizeObserver`.
- Keep `touch-action: pan-y` on the stage so a horizontal drag can select while
  normal vertical page scrolling continues.
- Keep the `html.gl` preflight gate, `.is-live` source swap and canvas absolute
  positioning. Those three rules prevent fallback flash and blank failures.
- The section owns no global reset. The small body style in `index.html` is
  preview furniture and may be deleted.

The first image inside each product article supplies both the fallback photo
and the Three.js texture. Use a transparent product cutout, fully visible with
space around its edges. `data-form` selects the presentation height in
`sprCreateSpeaker(record)`; it does not generate geometry or recolour the image.
All images decode before the stage mounts; a missing image restores the cards.

### Make It Yours

The fastest rebrand is entirely at the `.spr-range` root:

_Code snippet omitted: it ships with the download._

Edit the proposition and each article in the HTML. The script treats the
article data as the shared source for the canvas and active product footer:

| Product attribute | Purpose |
|---|---|
| `data-name` | Active model name and screen-reader announcement |
| `data-price` | Active price |
| `data-feature` | One defining reason to choose the model |
| `data-finish` | Finish label beside the swatch |
| `data-colour` | Six-digit finish swatch colour |
| `data-form` | `compact`, `wide`, `tall` or `tower` presentation size |
| `data-link` | Active model CTA URL |

Keep useful `alt` text and the complete product copy alongside each image.
The stage reuses the decoded image, preserving its alpha and natural ratio.

### Options

Set these on `[data-spatial-range]`:

| Attribute | Default | Description |
|---|---:|---|
| `data-drag` | `1` | `0` disables pointer drag while keeping buttons and keys |
| `data-snap-stiffness` | `112` | Spring pull toward the selected product |
| `data-snap-damping` | `18` | Spring damping; lower values overshoot more |

Numbers use an explicit parser, so `0` is a valid value rather than falling
back to the default. There is deliberately no wheel option: a product section
must not intercept page scrolling.

### Events and Programmatic Control

Each root dispatches:

| Event | Detail | When |
|---|---|---|
| `sprready` | `{ count }` | The canvas exists and the first frame has rendered |
| `sprchange` | `{ index, model }` | A different model reaches the active position |

_Code snippet omitted: it ships with the download._

Use `revert()`, not `kill()`. The GSAP context cleanup is where observers,
listeners, geometries, materials, textures, the renderer and the WebGL context itself are
released. Killing the context skips that work and eventually exhausts the
browser's context budget.

### Accessibility and Integration

- The four source articles are ordinary semantic content with real links.
- Previous/next controls are native buttons with visible
  focus styles. ArrowLeft and ArrowRight work while focus is anywhere in the
  section except a form field.
- The active product is announced through a polite live region after deliberate
  button, keyboard or completed drag selection.
- Touch uses Pointer Events and keeps vertical page scrolling through
  `touch-action: pan-y`. The section never handles wheel events.
- Under `prefers-reduced-motion: reduce`, no renderer is created. The complete
  product cards remain in a horizontal scroll-snap composition on narrow
  containers.
- With no JavaScript, missing GSAP, missing Three.js or failed WebGL, the same
  cards remain visible. The failure path does not log renderer errors because
  support is probed before a renderer is constructed.
- The section uses an `h2`. Change its level to match the host document outline;
  styling does not depend on the tag name.
- Container queries switch the layout from the host width rather than the
  viewport, so the section can sit inside a narrow CMS column.

Test your actual colour edits for contrast. The supplied palette targets a
minimum 4.5:1 for ordinary text and visible focus against both the mineral
ground and paper surface.

### Browser Support

The enhanced stage requires current WebGL and import-map support. The source
cards require neither. Browsers with WebGL disabled get the fallback before
Three.js attempts renderer construction, keeping the console clean.

### Performance

The stage uses twelve textured planes (three repeated slots per product),
with transparent edges sorted by depth, no lights and no post-processing.
Slots recycle beyond the visible arc with a smooth edge falloff, avoiding
visible jumps at the fourth-to-first boundary. Pixel ratio is
capped at `2` on fine pointers and `1.5` on coarse pointers. An
`IntersectionObserver` stops the frame loop off screen, and a `ResizeObserver`
on the section root resizes the stage for host-column and iframe changes.

The first performance lever is pixel ratio: change the fine-pointer cap from
`2` to `1.5` in `sprBuildRange`. Keep textures around 1200 pixels high to limit GPU memory. Do not remove
the off-screen loop gate or disposal path.

### Dependencies and Credits

| Dependency | Version | Role |
|---|---|---|
| Three.js | 0.180.0 | Renderer, perspective camera and transparent product textures |
| GSAP core | 3.15.0 demo pin; 3.12+ supported | `matchMedia`, scoped lifecycle/teardown and active-detail crossfade |

No GSAP plugins, smooth-scroll library, runtime fonts, photography or third-
party assets are used. GSAP does not drive the continuous 3D motion: the
renderer loop integrates the physical state and draws it each frame.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This website section is included only in the Vault, for existing and new owners. It is not sold individually. The standard licence covers unlimited personal and commercial projects; bundled assets retain their own licence requirements.

- [Get the Vault](https://gsapvault.com/pricing)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
