Skip to content

Motion

Spatial

A navigable 3D stage for floating content: drag to rotate, pinch or ⌘-scroll to zoom, with inertia, keyboard control and a clamped horizon.

Spatial SpatialItem
import { Spatial, SpatialItem } from '@anomalia/ui';

Notes

  • CSS 3D, not WebGL — real DOM, real text, real accessibility, and no dependency. For thousands of objects, lighting or occlusion, use a renderer instead.
  • Transitions are disabled while a pointer is down so the stage tracks the finger exactly; easing during a drag is what makes web 3D feel like a video of 3D.
  • Plain wheel scrolling is left alone deliberately. Zoom is ctrl/⌘+wheel — which is also what a trackpad pinch sends — so the page still scrolls over the scene.
  • Vertical rotation is clamped by maxTilt: an upside-down stage is disorientation, not freedom.
  • Keyboard: arrows rotate, +/- zoom, 0 resets. The stage is role="application" because it consumes the arrow keys.
  • Under reduced motion the idle drift and the release inertia stop; direct manipulation stays, because that motion is the user's own.

Examples

Gallery

A collage that happens to have depth. Drag to look around, pinch or ⌘-scroll to zoom, double-click to reset; arrows and +/− with a keyboard. The plates have no border, no caption and no card chrome — the work is the content, the space is the layout.

Services
Social media designs & feed creation

//2026 · drag to look

Build
Different

Week 34 · 12 plates

Use the arrow keys to rotate, plus and minus to zoom, and 0 to reset the view.

Designed for
Lindaria

Country — IT

Industry — Fashion

API

Spatial

PropTypeDefaultDescription
perspectivenumber1000Camera distance in px. Lower is a wider, more dramatic lens.
rotateX / rotateY / zoomnumber-8 / -18 / 1Bindable view state.
maxTiltnumber26Vertical rotation clamp, in degrees.
minZoom / maxZoomnumber0.6 / 2.2Zoom limits.
autoRotatebooleantrueIdle drift until the user takes over.
hintstring | nullGesture affordance; fades once the scene is touched.

SpatialItem

PropTypeDefaultDescription
x / y / znumber0Position in px. `z` is toward the viewer.
rotateX / rotateYnumber0Rotation about the object's own centre.
float / indexboolean / numbertrue / 0Idle bob; `index` offsets the phase so a group never moves in lockstep.
billboardbooleanfalseCounter-rotate to keep facing the camera — for text that must stay readable.

Every component also forwards the native attributes of its root element, plus class, so anything not listed here still works.