Live preview
Styled by its token map
acme.example

Spatial / 3D Web

Emerging

Interfaces built around a real-time 3D scene: a WebGL product model or abstract environment on a dark stage, driven by a scroll-linked camera, with minimal overlaid type. Layout is cinematography — Apple product pages and Spline-built portfolios are the reference points.

Palette
bg
#0d0d12
surface
#17171e
text
#f5f5f7
text-muted
#86868b
accent
#2997ff
border
#2a2a33

About this style

The spatial web crossed from novelty to mainstream when Apple's AirPods Pro page (2019) proved a scroll-scrubbed 3D product sequence could carry a flagship launch, and tools like Three.js, React Three Fiber, and Spline then collapsed the cost of following suit. The style is less a visual system than a cinematographic one: the designer's real decisions are camera paths, lighting rigs, and pacing, with 2D tokens reduced to a dark stage, one clean sans, and one accent. That is also why it is unforgiving — a mediocre glassmorphism site is merely bland, but a janky 3D site (dropped frames, scroll hijacking, ten-second loads) is worse than no site. Reach for it when the product's physical form or spatial data is genuinely the story: hardware launches, automotive configurators, architecture, portfolio showpieces. Skip it for content-heavy or conversion-critical flows, and always build the static fallback first; on the spatial web, performance budget and motion accessibility are design decisions, not engineering afterthoughts.

Vestibular risk: scroll-linked camera flight is a leading motion-sickness trigger — honor prefers-reduced-motion with static renders and crossfades, and keep camera velocity moderate
All content conveyed in the 3D scene must exist as real HTML text for screen readers; the canvas is aria-hidden decoration
Text over the live scene needs a dimming scrim or defocused backdrop to hold 4.5:1 — scene lighting changes can silently break contrast
Keyboard users need scroll-independent navigation (next/previous beat buttons) since drag-to-rotate is pointer-only
---
name: spatial-3d-web
description: Apply the Spatial / 3D Web visual design system when building or restyling websites and UI. Use whenever the user asks to build, theme, restyle, or "make it look like" Spatial / 3D Web, mentions WebGL site, 3D product showcase, scroll-driven 3D, or describes scroll-driven 3D camera moves, full-bleed WebGL canvas, dark stage with studio lighting — even if they don't name the style explicitly. Do NOT use for non-visual tasks or when another named design system is requested.
license: MIT
---

# Spatial / 3D Web Design System

Interfaces built around a real-time 3D scene: a WebGL product model or abstract environment on a dark stage, driven by a scroll-linked camera, with minimal overlaid type. Layout is cinematography — Apple product pages and Spline-built portfolios are the reference points.

Apply this system holistically: colors, type, spacing, radius, borders, shadows, and motion together produce the look. Token values are representative interpretations of the aesthetic, not an official spec. When in doubt, match the reference sites listed at the end.

## When to use

- Building a new page or component that should read as Spatial / 3D Web.
- Restyling existing UI to this aesthetic.
- The user names the style, an alias (WebGL site, 3D product showcase, scroll-driven 3D, R3F site, Spline site), or describes its traits: scroll-driven 3D camera moves; full-bleed WebGL canvas; dark stage with studio lighting; minimal overlaid UI; parallax depth layering; model rotation on drag.

## Design tokens

### Color palette

- Stage black — the void the scene is lit against: `#0d0d12` (--color-bg)
- Overlay panels, spec cards, chrome that floats above the canvas: `#17171e` (--color-surface)
- Primary overlaid text, Apple-style soft white: `#f5f5f7` (--color-text)
- Secondary copy and captions: `#86868b` (--color-text-muted)
- Interactive accent for links, CTAs, and hotspot markers: `#2997ff` (--color-accent)
- Hairlines on overlay chrome: `#2a2a33` (--color-border)

### Typography

- Display / headings: Inter (fallback: -apple-system, Helvetica Neue, sans-serif) (ideal: SF Pro Display, premium — use Inter as the free substitute)
- Body: Inter (fallback: -apple-system, Helvetica Neue, sans-serif)
- Type scale: 1.333 ratio, base 17px — computed steps: 17px / 23px / 30px / 40px / 54px / 72px (body / h5 / h4 / h3 / h2 / h1; scale further for display sizes)
- Headings: weight 700, line-height 1.1, letter-spacing -0.02em
- Body: line-height 1.3, letter-spacing 0

### Spacing, radius, border

- Spacing scale (px): 8, 16, 24, 40, 64, 96, 160, 240 — Full-bleed and cinematic: text beats are tiny islands (max 40ch) in vast scene space; scroll distance per section is 150–300vh to give camera moves room.
- Border radius: md 16px, lg 24px, pill 999px — Soft large radii on the few 2D overlay elements; the 3D scene itself owes nothing to border-radius.
- Border treatment: 1px solid #2a2a33 — Only overlay chrome gets borders; keep 2D furniture minimal so the scene stays the hero.

### Shadows

- overlay: `0 8px 32px rgba(0, 0, 0, 0.5)` — Floating spec cards and UI chrome above the canvas
- scene: `none` — Depth inside the scene comes from real-time 3D lighting, not CSS

### Layout

- Max content width: 1920px
- Fixed full-viewport canvas; HTML content scrolls in front of or around it
- Sections mapped to camera keyframes; text beats pinned at scroll stops
- Alternate composition sides per beat (text left, then right) so the model stays visible
- Hotspot markers on the model open small spec cards anchored in 3D space
- A traditional 2D footer returns after the scene ends — users need solid ground to finish on

### Effects

- Scroll-scrubbed camera animation along a spline path
- Cursor-tilt parallax (scene yaws 1–3° toward the pointer)
- Exploded-view assembly/disassembly tied to scroll
- Studio HDRI lighting with soft contact shadows under the model
- Depth-of-field rack focus between model and background at key beats

### Motion

- Easing: cubic-bezier(0.45, 0, 0.15, 1); durations 200ms / 500ms / 1200ms
- Camera position is a pure function of scroll — scrubbing back always reverses the shot
- Damped interpolation (lerp ~0.1) smooths scroll input; never 1:1 jitter
- Text beats fade+rise over 500ms as their camera stop is reached
- Under prefers-reduced-motion: replace camera flight with static renders and crossfades
- Idle state: model auto-rotates at ≤4°/s until first interaction

## CSS variables (drop-in)

```css
:root {
  --color-bg: #0d0d12;
  --color-surface: #17171e;
  --color-text: #f5f5f7;
  --color-text-muted: #86868b;
  --color-accent: #2997ff;
  --color-border: #2a2a33;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-pill: 999px;
  --shadow-overlay: 0 8px 32px rgba(0, 0, 0, 0.5);
  --border-default: 1px solid #2a2a33;
  --font-display: Inter, -apple-system, "Helvetica Neue", sans-serif;
  --font-body: Inter, -apple-system, "Helvetica Neue", sans-serif;
  --text-base: 17px;
  --leading-heading: 1.1;
  --leading-body: 1.3;
  --tracking-heading: -0.02em;
  --tracking-body: 0;
  --ease: cubic-bezier(0.45, 0, 0.15, 1);
  --duration-fast: 200ms;
  --duration-base: 500ms;
  --duration-slow: 1200ms;
}
```

Google Fonts: `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">`

## Component recipes

- **Nav:** Minimal translucent bar that fades out on scroll-down and returns on scroll-up; wordmark left, one accent CTA right — never a busy menu over a 3D scene
- **Hero:** Full-viewport scene with the product centered under studio light, one 64–96px headline, a scroll cue; the first scroll movement immediately proves the scene is live
- **Card:** Floating spec card: surface fill at ~90% opacity with backdrop blur, hairline border, 16px radius, anchored to a model hotspot with a 1px leader line
- **Button (primary):** Accent #2997ff pill, white 500-weight text, 44px height; subtle scale-up (1.03) on hover
- **Button (secondary):** Ghost pill with hairline border and text color; used for 'View specs' style secondary paths
- **Form fields:** Rare in this genre; when needed, surface fill with blur, hairline border, 12px radius, floating over the dimmed scene

Where this spec is silent (footers, responsive breakpoints, empty states), derive the treatment from the tokens above and the Do/Don't rules — never fall back to generic defaults. Every interactive element needs a visible keyboard focus state consistent with the style (use the accent color or the border treatment, not the browser default).

## Signature element

The scroll-scrubbed camera move: scrolling doesn't move the page, it flies the camera — the product rotates, explodes into components, or the environment travels past while short text beats fade in at choreographed stops. Spend boldness here; keep everything else quiet.

## Do

- Compress models aggressively (Draco/KTX2) and lazy-load the scene below a fast static first paint
- Give every camera move a narrative purpose — each beat should reveal a feature
- Keep overlaid text short and high-contrast against a dimmed or defocused scene region
- Ship a full static-image fallback for WebGL failures and low-power devices

## Don't

- Don't hijack scroll speed or add scroll inertia the user didn't ask for
- Never body-lock the page behind a multi-second loading screen — show the stage immediately
- Don't place small text directly over high-frequency scene detail
- Avoid gratuitous camera spins that exist only because the tech allows them

## Accessibility notes

- Vestibular risk: scroll-linked camera flight is a leading motion-sickness trigger — honor prefers-reduced-motion with static renders and crossfades, and keep camera velocity moderate
- All content conveyed in the 3D scene must exist as real HTML text for screen readers; the canvas is aria-hidden decoration
- Text over the live scene needs a dimming scrim or defocused backdrop to hold 4.5:1 — scene lighting changes can silently break contrast
- Keyboard users need scroll-independent navigation (next/previous beat buttons) since drag-to-rotate is pointer-only

## Reference sites

- Apple product pages: https://www.apple.com
- Spline: https://spline.design
- Three.js: https://threejs.org
- Awwwards 3D sites: https://www.awwwards.com

For the exhaustive machine-readable spec, see references/tokens.md and tokens.json in this skill folder.

Install this skill

Claude Code — download the zip, then unzip into your skills folder
unzip spatial-3d-web.zip -d ~/.claude/skills/
shadcn/ui — apply as a theme to any shadcn project
npx shadcn add https://claude-design-skills.convoke.software/r/spatial-3d-web.json
claude.ai — upload the zip as a custom skill
Settings → Capabilities → Skills → Upload skill → spatial-3d-web.zip
Download .zip