Skip to content
WANCRAFT

H.1823D & Experimental

Extruded Text

Display text with real 3D depth from stacked, shaded layers that turns toward the pointer on a spring.

NewReactMotionCSSTailwindintermediate

Overview

Extruded Text builds a solid 3D word from stacked copies of the text at increasing translateZ depths inside a preserve-3d group, so the extrusion is genuinely three-dimensional and shows the correct sides as the word turns. The group rotates toward the pointer on a spring and, while the pointer is away, sways gently around a resting angle. Each layer blends from the side colour to an end colour and darkens with depth, the layer right behind the face is lifted into a bevel highlight, and a light term driven by the current angle (a motion value written to a CSS variable) brightens or shades the sides as it turns, all without re-rendering. Layers are capped at 24, only the face is exposed to assistive tech, and reduced motion holds a static angle.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/extruded-text.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/extruded-text.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/extruded-text.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { ExtrudedText } from "@/components/ui/extruded-text";

export function ExtrudedTextExample() {
  return (
    <ExtrudedText as="h2" className="text-8xl font-extrabold tracking-tight">
      DEPTH
    </ExtrudedText>
  );
}

03Props

PropTypeDefaultDescription
childrenstring—Required. The display text.
as"h1" | "h2" | "h3" | "p" | "div" | "span""div"Element to render.
depthnumber14Stacked layers behind the face (capped at 24).
spacingnumber1.5Distance between layers in px.
sideColorstring"#FF7448"Side colour nearest the face.
sideColorEndstring"#3B1206"Side colour at the back; layers blend toward it.
maxTiltnumber18Maximum rotation toward the pointer in degrees.
spring{ stiffness: number; damping: number; mass: number }{ stiffness: 120, damping: 14, mass: 0.8 }Spring for the rotation.
swaybooleantrueGentle idle sway while the pointer is away.
perspectivenumber900CSS perspective in px.

04Features

  • 01True 3D extrusion: text copies at stepped translateZ inside a preserve-3d group
  • 02Turns toward the pointer on a spring; returns to a resting angle on leave
  • 03Per-layer colour blend from side to end colour, depth darkening and a bevel highlight
  • 04Angle-driven lighting via a CSS variable fed by a motion value — no re-renders
  • 05Idle figure-of-eight sway that pauses offscreen and in hidden tabs
  • 06Layer count capped at 24 for performance; the face is plain, selectable text
motion · springmotion · continuousinput · pointerinput · hover

05Accessibility

  • Only the front face is in the accessibility tree; every depth layer is aria-hidden and unselectable.
  • The `as` prop keeps document structure (e.g. an h2 headline).
  • Touch input never rotates the text, so scrolling is unaffected.
  • prefers-reduced-motion holds a static resting angle with no sway or pointer tracking.

06Limitations

  • Each layer repeats the text, so very long passages multiply the DOM; use it for short display words.