Glass Gallery
v1.0.1An immersive 3D glass-morphic photo gallery cube that disassembles into a flat responsive image collage on scroll.
Framer Remix Link
https://framer.link/8tgW8YPInstallation
Run once in your project root to configure paths and dependencies:
npx vectorvesper initDownloads and registers the component in your project:
npx vectorvesper add glass-galleryIf installing manually or managing your package lock:
npm install three @react-three/fiber @react-three/drei gsap @gsap/reactUsage
Import
Usage
WebGL — render it on the client only
On Next.js, load it with ssr: false from a Client Component, as below. Vite apps need nothing extra.
Props
Photos mounted on panes of thick glass, arranged as a block that turns as you scroll and then unfolds into a flat grid. It drifts on its own when you leave it alone and tilts toward the cursor.
<GlassGallery />
The whole scene. Fills its container, so give the parent a height.
| Prop | Type | Default | Description |
|---|---|---|---|
images* | string[] | — | Photo URLs. Required. Supply at least as many as the mode has faces, or they repeat to fill. |
mode | "square" | "rect" | "quad" | "quad" | How the panes are arranged before they unfold — a cube of six, a slab of twelve, or twenty-four tiles. |
cubeSize | number | 0.5 | Overall scale of the block in the scene. |
autoSpinSpeed | number | 0.15 | How fast it turns on its own when nothing is happening. 0 holds it still. |
scrollSpins | number | 1.0 | Full turns it makes across the scroll as it unfolds. |
mouseTiltIntensity | number | 1.0 | How far it leans toward the cursor. 0 removes the tilt. |
glassThickness | number | 1.3 | How deep each pane is. Thicker glass bends what is behind it more and reads heavier. |
glassRoughness | number | 0.12 | Surface finish, 0–1. Low is polished; higher frosts the pane. |
glassOpacity | number | 0.16 | How solid the glass itself looks, apart from the photo on it. |
glassColor | string | "#ffffff" | Tint of the glass. |
photoOpacity | number | 1.0 | Opacity of the photos on the panes. |
hoverTransparency | boolean | false | Fades the near panes on hover so you can see through to the far side of the block. |
backgroundColor | string | "#000000" | Colour behind the scene. |
galleryItemWidth | number | derived from the layout | Overrides the width of a tile once the block has unfolded into a grid. |
galleryItemHeight | number | derived from the layout | The same for height. |
gridGapX | number | derived from the layout | Horizontal spacing between tiles in the unfolded grid. |
gridGapY | number | derived from the layout | Vertical spacing. |
staticPreview | boolean | false | Renders one still frame with no scroll handling, drifting or tilt. Use it for a thumbnail, or as the reduced-motion fallback. |
children | React.ReactNode | — | Rendered over the scene, for overlay type. |
className | string | "" | Applied to the wrapper. |
style | React.CSSProperties | — | Inline styles merged onto the wrapper. |
Presets
| Preset | Description | Key Overrides |
|---|---|---|
"square" | Six panes as a cube. | — |
"rect" | Twelve panes as a slab. | — |
"quad" | Twenty-four tiles. The default, and the busiest. | — |
<GlassGalleryOverlay />
A ready-made caption panel sized to sit over the scene. Takes no props — drop it in as a child and edit the markup.
Examples
import GlassGallery from "@/components/vv/glass-gallery/GlassGallery";
<div className="h-screen">
<GlassGallery images={photos} />
</div><GlassGallery
images={photos}
mode="square"
cubeSize={0.7}
glassRoughness={0.4}
glassColor="#cfe3e8"
hoverTransparency
/><GlassGallery images={photos} staticPreview />staticPreview is one: pass it when the preference is set and the scene renders as a still image with the same look.quad costs noticeably more than square. If a page carries several galleries, put the ones below the fold in staticPreview.ssr: false if your route renders on the server.