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,0resets. The stage isrole="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
Different
Week 34 · 12 plates
API
Spatial
| Prop | Type | Default | Description |
|---|---|---|---|
perspective | number | 1000 | Camera distance in px. Lower is a wider, more dramatic lens. |
rotateX / rotateY / zoom | number | -8 / -18 / 1 | Bindable view state. |
maxTilt | number | 26 | Vertical rotation clamp, in degrees. |
minZoom / maxZoom | number | 0.6 / 2.2 | Zoom limits. |
autoRotate | boolean | true | Idle drift until the user takes over. |
hint | string | null | — | Gesture affordance; fades once the scene is touched. |
SpatialItem
| Prop | Type | Default | Description |
|---|---|---|---|
x / y / z | number | 0 | Position in px. `z` is toward the viewer. |
rotateX / rotateY | number | 0 | Rotation about the object's own centre. |
float / index | boolean / number | true / 0 | Idle bob; `index` offsets the phase so a group never moves in lockstep. |
billboard | boolean | false | Counter-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.