3D Spherical Gallery

A draggable 3D room of image cards wrapped around the viewer — hover to bring a card forward, click to follow its link. Fully configurable, no assets required.

3.3k

1.3k copies

Image preview

Live preview

Abstract dark glass form
Preview

About this component

3D Spherical Gallery places your images on the inside of a sphere and puts the
viewer at its centre. Dragging looks around the room with real momentum; the
horizontal axis loops forever while the vertical axis is rubber-banded to a
limit you set. Cards fade toward black as they move away from the centre of
view, so the composition always reads as one focused wall rather than a busy
sphere.

Cards are laid out on an exact grid — every row is a straight horizontal line
and the columns line up vertically. From there you can dial in as much
irregularity as you want: stagger alternate rows, leave random holes, vary the
size, depth and angle of each card, or add a slight tilt. Spacing works in
either direction: set the card size and let the gaps fall out, or type the gaps
you want and let the component solve for the card size.

Drop your own images in and each card can carry a link, opening in the same tab
or a new one, or fire a Framer interaction instead. A click is told apart from a
drag by distance, duration and whether the press landed and released on the same
card, so a flick that starts on a card just spins the room.

With no images set, the component draws generated "site screenshot" placeholders
from a seeded random source — so it looks finished the moment it lands on the
canvas, and stays identical between reloads until you change the seed.

Built on Three.js with no other dependencies. It rebuilds only when structural
props change; colour, motion and hover values are read live each frame, so those
sliders retune instantly. Frames are skipped when nothing is moving, animation
pauses on the Framer canvas, and everything is disposed on unmount.

Key features

Drag to explore — infinite horizontal rotation with momentum and glide;
vertical travel is rubber-banded to a configurable tilt limit

  • Separate drag and coast smoothing — a tight, attached feel while dragging
    and a soft settle after release

  • Hover focus — the card under the cursor grows, steps toward the viewer,
    brightens and gains a halo while everything else dims back

  • Click-through links — per-card URL, same tab or new tab, plus an
    onCardTap event handler for Framer interactions

  • Click vs drag detection — distance, duration and same-card checks, so
    dragging from a card never triggers navigation

  • Press feedback — the card dips slightly while held

  • Two spacing modes — set the card size and read off the gaps, or set the
    gaps and let the card size be solved for (honoured at the tightest row)

  • Exact grid or scattered — stagger, fill density, size, depth, angle and
    tilt variation, all from zero to as loose as you like

  • Depth falloff — distance fog plus an angular fade curve with adjustable
    start, end, curve and floor

  • Cover or contain — images cover-cropped via UV transform, or the card
    reshaped to the image's own ratio

  • Generated placeholders — six procedural site-screenshot layouts, twelve
    palettes, editable name and headline lists, all seeded and reproducible

  • Cursor parallax — a subtle lead toward the pointer that eases away on press

  • Auto drift — idle rotation with direction, speed and delay, pausing on hover

  • Full styling control — background, fog colour, glow colour, vignette
    colour and size, corner radius, edge light

  • Centre overlay — title, font, colour, caption, tracking, offset and backdrop

  • Performance minded — idle frames skipped, DPR cap, optional antialias,
    paused on the Framer canvas, full WebGL disposal on unmount

  • Responsive — sizes to its frame via ResizeObserver, any width and height

  • Touch ready — pointer events throughout, no hover state stuck on mobile

  • No CORS pitfalls — images are never drawn to a canvas, so cross-origin
    sources work

API reference

All props are optional — every value falls back to its default, and partial
objects are merged, so setting one field of a group leaves the rest intact.

Content

Prop

Type

Default

Description

images

Array of { image, link, newTab }

[]

Cards to show. image is a ResponsiveImage, link a URL, newTab a boolean. Empty means generated placeholders. Plain image entries are also accepted.

imageFit

"cover" | "contain"

"cover"

Cover crops to the card ratio via UV transform; contain reshapes the card to the image.

seed

number (1–9999)

7

Seeds all randomness — placeholder art, shuffles, jitter, holes.

onCardTap

EventHandler

—

Fires on a card click with the card's index.

grid

Prop

Type

Default

Range

Description

rows

number

7

1–16

Horizontal rows of cards.

columns

number

16

3–40

Cards per row; also sets column alignment.

gapMode

boolean

false

—

false: you set cardWidth. true: you set gapX/gapY and card size is solved.

cardWidth

number

5

0.5–14

Card width in world units. Used when gapMode is off.

gapX

number

4

0–14

Horizontal gap, honoured at the tightest row. gapMode on.

gapY

number

3.1

0–14

Vertical gap between rows. gapMode on.

cardAspect

number

1.6

0.3–3.5

Card width ÷ height.

cornerRadius

number

0.045

0–0.5

Fraction of the card's short edge.

edgeLight

number

0.28

0–1

Brightness of the rim highlight around each card.

distance

number

23

6–70

Sphere radius — how far the cards sit from the viewer.

bandTop

number

0.24

0.02–0.5

Top row's latitude, × π from the pole. gapMode off.

bandBottom

number

0.76

0.5–0.98

Bottom row's latitude. gapMode off.

stagger

number

0

0–1

Offsets alternate rows by up to half a slot.

density

number

1

0.2–1

Chance a slot is filled; below 1 leaves holes.

sizeVariation

number

0

0–0.6

Per-card random size spread.

depthVariation

number

0

0–6

Per-card radial offset, in world units.

angleJitter

number

0

0–0.6

Per-card offset from its exact grid slot.

tilt

number

0

0–0.3

Per-card random roll, in radians.

lens

Prop

Type

Default

Range

Description

fieldOfView

number

74

25–115

Camera FOV in degrees.

maxPixelRatio

number

2

1–3

Caps device pixel ratio.

antialias

boolean

true

—

WebGL MSAA.

look

Prop

Type

Default

Range

Description

background

color

#000000

—

Behind the WebGL canvas.

fogColor

color

#000000

—

Colour cards fade toward with distance.

fog

number

0.016

0–0.08

Exponential fog density.

glow

number

0.16

0–0.8

Halo strength behind each card.

glowColor

color

#ffffff

—

Halo tint.

fadeStart

number

0.4

0–1

Facing value where a card is fully lit.

fadeEnd

number

0.985

0–1

Facing value where it has faded out.

fadeCurve

number

1.12

0.3–4

Exponent on the falloff; higher is more contrasty.

minBrightness

number

0.05

0–0.5

Brightness floor for the darkest cards.

vignette

number

1

0–1

Vignette opacity.

vignetteColor

color

#000000

—

Vignette colour.

vignetteSize

number

115

60–200

Vignette spread, in percent.

motion

Prop

Type

Default

Range

Description

drag

boolean

true

—

Enables pointer dragging.

dragSpeed

number

0.0032

0.0005–0.012

Radians per pixel dragged.

invert

boolean

false

—

Reverses drag direction.

lockVertical

boolean

false

—

Horizontal-only dragging.

wheel

boolean

true

—

Enables wheel and trackpad rotation.

wheelSpeed

number

0.0016

0–0.01

Radians per wheel unit.

friction

number

0.935

0.75–0.995

Momentum decay after release; higher glides longer.

smoothing

number

0.1

0.02–0.5

Easing while coasting.

dragSmoothing

number

0.32

0.05–1

Easing while dragging; higher tracks the pointer more tightly.

pitchLimit

number

0.4

0–1.2

Max up/down tilt, in radians.

rubber

number

0.28

0–1

Resistance when dragged past the tilt limit.

overshoot

number

0.09

0–0.3

How far the rubber band may visibly stretch, in radians.

autoDrift

number

0.28

0–3

Idle rotation speed; 0 disables.

driftDirection

"left" | "right"

"left"

—

Idle rotation direction.

driftDelay

number

0.6

0–6

Seconds of stillness before drift starts.

parallax

number

0.02

0–0.12

Lead toward the cursor, in radians.

startAngle

number

0

−180–180

Initial horizontal rotation, in degrees.

startPitch

number

0

−40–40

Initial vertical tilt, in degrees.

hover

Prop

Type

Default

Range

Description

enabled

boolean

true

—

Mouse only; touch has no hover state.

scale

number

0.16

0–0.8

How much the card grows.

lift

number

0.055

0–0.3

Step toward the viewer, as a fraction of distance.

brightness

number

0.45

0–2

Extra brightness on the hovered card.

glow

number

3.2

0–10

Halo multiplier on the hovered card.

dim

number

0.3

0–0.9

How far every other card drops back.

speed

number

0.16

0.03–0.6

Hover in/out easing.

pauseDrift

boolean

true

—

Holds auto-drift still while hovering.

cursor

boolean

true

—

Grab / grabbing / pointer cursors.

click

Prop

Type

Default

Range

Description

enabled

boolean

true

—

Enables card links and onCardTap.

pressScale

number

0.05

0–0.3

How far the card dips while held.

tolerance

number

6

0–40

Pixels of movement still counted as a click.

holdTime

number

900

150–2000

Milliseconds above which a press is a hold, not a click.

overlay

Prop

Type

Default

Range

Description

showTitle

boolean

true

—

Shows the centre wordmark.

title

string

"Made with\nSquarespace"

—

Newlines become line breaks.

titleFont

font

Georgia 64 / 1.05em

—

Extended font control.

titleColor

color

#ffffff

—

Title colour.

textShadow

number

1

0–1

Shadow strength behind the title.

subtitle

string

"Drag to explore"

—

Caption under the title.

subtitleColor

color

rgba(255,255,255,0.42)

—

Caption colour.

subtitleSize

number

11

6–32

Caption size in pixels.

subtitleSpacing

number

3.5

0–12

Caption letter spacing.

subtitleUppercase

boolean

true

—

Uppercases the caption.

subtitleGap

number

18

0–80

Space between title and caption.

offsetY

number

0

−400–400

Vertical offset of the whole overlay.

backdrop

number

1

0–1

Dark pool behind the overlay for legibility.

placeholder

Used only while images is empty.

Prop

Type

Default

Range

Description

lightRatio

number

0.82

0–1

Share of light versus dark palettes.

chrome

number

0.38

0–1

Chance a card gets a browser title bar.

names

string

27 names

—

One per line; used for card headings.

headlines

string

14 lines

—

One per line; used for editorial cards.

Notes

  • World units. cardWidth, gapX, gapY, depthVariation and distance
    share one scale. Raising distance widens gaps at a fixed card size.

  • Rebuild vs live. images, imageFit, seed, grid, placeholder,
    lens.fieldOfView and lens.antialias rebuild the scene. look, motion,
    hover, click and overlay are read every frame and apply instantly.

  • Dependency. Three.js r160, imported from https://esm.sh/three@0.160.1.
    Swap that line for import * as THREE from "three" if your project resolves
    npm packages directly.

  • Canvas behaviour. On the Framer canvas, auto-drift, hover and navigation
    are suppressed; all three run in Preview and on the published site.

Details

Category

Gallery

Media

Image

Views

3.3k

Copies

1.3k

Paste directly onto your Framer canvas.

Need a custom version?

We adapt components to your brand, motion and CMS setup.