Functional 3D vs. Decorative 3D Web Interfaces
Most 3D on the web today is decorative: a scroll-scrubbed animation playing inside a canvas that the browser treats as one opaque rectangle. Functional 3D is the opposite commitment — what appears inside the scene is structured like a document: elements with stable addresses, layout the browser's CSS can solve, events the scene delivers to them, and state the document keeps and can save. This page defines both terms, names the failure pattern that separates them, and compares the two architectures capability by capability.
That commitment is what the Scene Document Model provides: it gives pure 3D elements the structure and usability of a document. Decorative 3D has none of it.
The Scroll-Triggered Canvas Trap
The Scroll-Triggered Canvas Trap is the pattern behind most "3D websites" shipping today: embed a canvas, load a 3D model, and wire the page's scroll offset to an animation timeline — so the scene behaves not as an interface but as a video whose playhead is the scroll bar.
The Scroll-Triggered Canvas Trap — the dominant web-3D pattern in which a canvas plays a scroll-driven animation of a loaded model (typically a glTF asset rotating, exploding, or flying past the camera as the user scrolls) and nothing more. The result is functionally a heavy, non-interactive video: no text elements, no operable controls, and no navigation exist inside the rectangle, and the only input the scene understands — scroll — it understands only as scrubbing a playhead.
The recipe is consistent no matter which rendering API draws the pixels. A modeling tool exports an asset; a viewer library loads it into a canvas; a scroll listener maps the document's scroll position onto rotation angles, a camera dolly, or exploded-view progress. Any words the user can see were baked into textures when the asset was exported. The pattern is a trap in a precise sense: it consumes the budget a real spatial interface would need — megabytes of model data, a GPU pipeline, and the page's one universal gesture — and returns none of the interactivity that spending should buy. The page underneath still does all of its actual work in flat 2D, stacked above or below the canvas.
Decorative 3D is not a failure of craft; as motion design, much of it is excellent. It is a ceiling of architecture. Nothing about the pattern can be incrementally improved into an interface, because the document model never entered the canvas in the first place — and everything a browser knows how to do, it does to documents.
Defining Functional 3D: state, layout, and interaction
Functional 3D means the three responsibilities that make a web page work — state, layout, and interaction — apply to the 3D scene's own elements instead of being left to the flat page around it.
Functional 3D — a 3D interface whose elements behave as document content: addressable by id and label, positionable by layout the browser's own CSS solves rather than only by coordinates frozen at export, reached by input the scene delivers to them as messages, and carrying document state that persists, animates, and serializes. A Functional 3D scene is a document with a camera, not a video with a scroll bar. The architecture that delivers it on the open web is the 3D Spatial Web Interface.
Decorative 3D — a 3D visual that carries no live document content: it is looked at, not used. Its text is pixels baked into textures, its controls are pictures of controls, and it holds no state beyond an animation's playback position. Interaction, where it exists at all, is limited to scrubbing that playback.
Each word in the definition is a testable property, not a mood. State: can the scene be saved and reloaded with its behavior intact, or does refreshing the page reset everything to frame zero? Layout: when content changes size, does anything reflow, or were all positions hard-coded when the asset was exported? Interaction: does a click reach an addressable element with something listening for it, or does it vanish into the canvas? Decorative 3D fails all three by construction. The sections below ground the passing answers in the shipped mechanisms of one reference implementation.
The definition's demands fall on the 3D objects themselves: a sphere, a light, or a group must behave like a document element — addressable by id and label, animatable by named clip, governable by a state machine, serialized in the scene document. A scene qualifies as Functional 3D only when its 3D objects gain function they never had in a display list.
Why decorative 3D fails basic web expectations
Decorative 3D fails because the browser sees a canvas as a rectangle of pixels — there is nothing inside it to read, select, focus, or submit.
Every baseline expectation breaks at the canvas boundary. Find-in-page finds nothing, because the visible text was rasterized into a texture before the page ever loaded. Nothing can be selected or copied. The Tab key has nowhere to go: no focusable element exists inside the rectangle, so keyboard users skip the entire experience. A "button" rendered in the scene is a picture of a button, and submitting anything means leaving the canvas for a real form elsewhere on the page. Assistive technology inherits the same blankness, because the typical viewer places no document structure inside the canvas to expose.
Functional 3D does not turn the scene's content into DOM, so it does not restore these expectations wholesale, and the honest boundary belongs in the definition. In the reference implementation described below, keyboard support for scene content is navigation-level (scroll detents and camera modifier keys, with guards that keep those keys from being stolen while a form field has focus); the exception is its glass UI controls: each operable control (button, switch, checkbox, radio, slider, text field) keeps its state in a native, focusable form element placed right after the canvas in DOM order, so Tab reaches them in authored order, and the label and the progress bar keep native but unfocusable counterparts (a span, a progress element); every counterpart stays in the accessibility tree. Document structure inside the scene is a precondition for deeper accessibility, not a finished compliance claim.
The comparison
The table states the contrast capability by capability; the paragraphs after it ground the right-hand column in shipped mechanisms.
| Capability | Decorative 3D (typical canvas glTF viewer) | Functional 3D (a 3D Spatial Web Interface) |
|---|---|---|
| Interaction | scroll-linked animation only, canvas swallows input | pointer hits are picked against scene elements and delivered as messages their state machines answer |
| Layout | hard-coded matrix coordinates | authored coordinates, or, for elements seated in a rig, solved by the browser's own CSS grid/flex engine and projected to world space |
| Content | baked textures, text is pixels | text is an element the document stores as its string and font, laid out as glyphs at load |
| State | none (a playback) | a scene document: named animation clips, state machines, save/load |
| 3D objects | anonymous nodes in a display list — nameless, stateless, unaddressable | document elements: addressable by id and label, carrying named clips and state machines, serialized in the scene document |
| Shipping | viewer code + model files wired into one page | a self-contained static folder — one player file, the scene document and the assets it references, on any host |
Interaction. In the reference implementation behind these pages — the Software 4 Senses
3D Spatial Web Studio — a press or hover over the scene is resolved by a CPU ray cast from the
pointer through the same camera model the renderer ray-marches, against the elements registered as
pickable; a state machine binding that listens for pointer messages on a primitive registers it.
The nearest hit becomes a message on the scene's message bus (ui hover, unhover,
press, release, or drag, carrying the element's id), and the bound state machine answers it with a
transition. Typing reaches the scene through the glass UI controls: a text field's state is a native
text input, and its glyphs in the scene follow the input's value.
Layout. Functional 3D does not reimplement layout; it delegates it. A scene element is not a DOM box, so author CSS cannot position it directly; instead the layout subsystem builds an offscreen measurement twin, an empty box at each occupant's declared size, lets the author's own CSS grid lay the boxes out, measures the resulting rectangles, and converts them into world-space poses through a pure solver at a fixed contract of 50 CSS px = 1 world unit. CSS remains the layout language; the third dimension is a projection of its output, so wrapping and reflow keep working.
Content. The words in a Studio scene are not baked into a texture; only each character's distance field is, once per font, in that font's atlas. The scene document stores a text element as its string, its font atlas, and its size, and the player lays the letters out as distance-field glyph records when the scene loads (see text in ray-marched scenes), so changing the words is an edit to the document, not a re-export of an asset.
State. A Functional 3D scene is stateful the way a document is, not the way a video is — this is the Scene Document Model at work, giving the solids themselves the kind of persistent, addressable state a form field takes for granted on a 2D page. In the Studio, any scene record can be driven by named animation clips executed by the browser's native Web Animations API — keyframes interpolate on registered CSS custom properties and are sampled once per animated target per frame — and per-object state machines are plain JSON: declarative bindings subscribe to a scene-wide message bus and fire transitions that execute a closed set of eight validated action operations. All of it serializes. The scene document carries the reconstitutable definitions (clip keyframes, machine JSON), while live state — playback progress, a machine's current state, message history — is reported separately for inspection.
Shipping. A finished Functional 3D scene ships as static files: one self-contained player bundle, the scene document, and the fonts, models and pictures it references (plus licence and notice files), servable from any static host with no server runtime. The player carries its WGSL pre-baked per capacity profile and catalog tier — a few closed sets of primitive types — and boots the smallest tier that covers the types the scene document declares; nothing about a running scene's contents ever triggers a shader recompile. Rendering requires a WebGPU-capable browser.
How a Functional 3D interface is built
A Functional 3D interface is authored as a scene document, not programmed frame by frame. In the Studio, scenes are composed from a catalog of primitives rendered by ray marching signed distance functions in a WebGPU compute shader; spatial layout is delegated to CSS as described above; behavior is authored as named clips and JSON state machines; and the result exports as a scene document that the player file replays. The nouns an author works with — cards (slabs), rigs, rails — are documented in the Studio's tutorial, How to build a scene, and the architecture they implement is defined on the 3D Spatial Web Interface page.
Related reading
- What Is a 3D Spatial Web Interface? — the canonical definition of the architecture the table's right-hand column describes.
- The Scene Document Model: Document Structure for 3D Elements — how pure 3D elements (solids, lights, groups) gain the addressability, state, and serialization of a document.
- Event Propagation in 3D: From Screen Space to Scene Records — how a click or hover becomes a CPU ray pick and a message on the scene's bus, and how that bus rebuilds DOM-style bubbling over the scene's record tree.
- Synchronizing Web Animations API Easing with a GPU Render Loop — how the browser's own animation engine drives 3D scene records.