ModelViewer
model-viewerDisplays a CSS 3D model stage with drag rotation, inertia, parallax, and auto-rotate.
Usage
Basic usage
Put any children as a "model" on the stage - drag rotation, mouse parallax, hover tilt are all enabled by default.
<ModelViewer height={320}>
{/* Any node can be used as a "model" */}
<YourModel />
</ModelViewer>Automatic rotation
autoRotate makes the model rotate at a constant speed around the Y axis, and autoRotateSpeed controls the angular velocity.
<ModelViewer height={320} autoRotate autoRotateSpeed={28}>
<YourModel />
</ModelViewer>Minimalist interaction
Turn off parallax/hover/contact shadow/reset buttons, leaving only pure drag rotation.
<ModelViewer
height={300}
enableMouseParallax={false}
enableHoverRotation={false}
showContactShadow={false}
showResetButton={false}
>
<div
className="grid size-32 place-items-center rounded-2xl text-4xl font-bold text-white"
style={{
background: "linear-gradient(135deg, var(--color-chart-2), var(--color-chart-5))",
transform: "translateZ(40px)",
}}
>
UI
</div>
</ModelViewer>When to Use
Use it to place any React node—a product image, card, SVG, or emoji—on a 3D stage with inertial drag rotation, parallax, hover tilt, and a contact shadow. It uses CSS 3D instead of three.js and does not load GLTF or FBX assets. For magnification, use Lens; for a glare-only hover effect, use GlareHover.
Import
import { ModelViewer } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| width | number | string | "100%" | Stage width, constrained by outer container |
| height | number | string | 360 | Stage height |
| defaultRotationY | number | -20 | Initial yaw angle (around Y, °), accumulated when dragging |
| defaultRotationX | number | 12 | Initial pitch angle (around X, °), accumulated when dragging |
| perspective | number | 1000 | CSS perspective depth in pixels; lower values create more exaggerated perspective |
| enableManualRotation | boolean | true | Allow the mouse to drag and rotate, and let go to slow down with inertia |
| enableMouseParallax | boolean | true | Mouse parallax (the model is slightly displaced when the pointer moves) |
| enableHoverRotation | boolean | true | Hover tilt (the model tilts towards the pointer) |
| autoRotate | boolean | false | Automatically rotate around the Y-axis at a constant speed, superimposed with manual dragging |
| autoRotateSpeed | number | 24 | Rotation angular speed (°/s), only valid for autoRotate |
| showResetButton | boolean | true | Shows the "Reset Perspective" button in the upper-right corner |
| showContactShadow | boolean | true | Shows a soft contact shadow beneath the content |
| className | string | — | Additional class name for the root container |
| style | CSSProperties | — | Inline styles forwarded to the root container |
Slots
| Slot | Type | Description |
|---|---|---|
| children | ReactNode | Place the "model" in the center of the 3D stage, and apply rotation/parallax/tilt uniformly through the components |
Usage Guidelines
- This is a CSS 3D stage, no real GLTF/FBX/OBJ is rendered;
childrenshould be flat/pseudo 3D content, the sense of depth comes from the outerpreserve-3dsublayer itself usingtranslateZ. - This is a client component because dragging and inertia use rAF. Under reduced motion, inertia and rotation are suppressed.
- Contents that require
transform-style: preserve-3dfor multi-layer cubes must be set in children by yourself, and the component is only responsible for the overall rotation/parallax container.
Related
BorderBeam · ShineBorder · GlareHover · Lens · AnimatedBeam · OrbitingCircles
Playground
<div className="overflow-hidden rounded-xl"
style={{ background: "oklch(0.16 0.02 255)" }}>
<ModelViewer
height={320}
autoRotate={false}
autoRotateSpeed={24}
enableMouseParallax={true}
enableHoverRotation={true}
showContactShadow={true}
>
{/* Any children as "model" */}
<YourModel />
</ModelViewer>
</div>