Overview
Pointer preserve-3d parallax is a depth illusion built from a real 3D stack, not a flat card that happens to rotate. The important distinction is ownership: the scene owns perspective, the stack preserves 3D children, and each layer has a fixed translateZ depth. Pointer input only nudges camera variables inside a small, clamped range, so the object feels responsive without changing layout.
When to use it
Use it for compact hero objects, feature cards, editor thumbnails, and product surfaces where depth helps the user inspect hierarchy. It works best when the animated thing is one self-contained object with a clear front, middle, and back plane. Skip it for dense reading content, primary form controls, or required workflows where pointer tracking would make the target feel like it is moving away from the user.
How it works
The wrapper owns perspective, the stack owns transform-style: preserve-3d, and each child uses translateZ for depth. JavaScript maps pointer coordinates to CSS variables such as --rx and --ry, then CSS applies those variables to the single stack transform.
Production gotchas
Do not rotate the whole page, animate layout dimensions, or let pointer values become unbounded. Large angles make text hard to read and can make perceived hit targets drift away from their actual boxes. Inspector controls must affect depth, tilt, duration, or easing; decorative controls that do not affect the animation should be removed.
Accessibility
Depth is decorative, so the content must remain readable without motion. Pair pointer tracking with focus-visible parity and provide an idle pose that still communicates layers for touch and keyboard users. Reduced motion should flatten live tracking while keeping the stacked planes visible, rather than removing the visual hierarchy entirely.
References
Implementation depth
This is the pointer-reactive version of preserve-3d layering, not another static cube. The scene owns perspective, the stack owns transform-style: preserve-3d, and each layer has a stable translateZ depth so pointer movement changes camera feel without changing document layout.
Keep pointer input bounded and optional. Map client coordinates into small CSS variable ranges, clamp the tilt, and provide a focus or idle state that reads as depth without requiring mouse movement. Reduced motion should flatten the live tracking while keeping the layers visible.
The showcase examples should stay method-based: a depth stack, a glare plane, and a foreground/background split are different expressions of the same 3D contract. Changing only the label or color would not be enough evidence that the slug deserves a separate preset.
Production code needs a clear event boundary. One pointermove listener on the root should update variables; child layers should not each track input, and the transformed surface should not become the source of layout, scroll, or hit-target changes.