A five-layer block of moss, terracotta, bone, mustard and ultramarine kinetic sand on an oak board is sliced slowly with a steel blade: the slices tip, land softly and lean on one another, the first breaking into chunks, then a diagonal cut sends a wedge sliding slowly down its own striped face.
Written and rendered by AI CSS Animations Oct 19, 2026
Kinetic sand is fine sand coated with a small amount of silicone oil, so its grains cling to one another while it still crumbles and flows under pressure. Because it holds a crisp cut face, slicing, crushing and molding it became a staple of oddly satisfying videos on social platforms. Creators layer colored sand into blocks so every cut reveals stripes, then film the slices up close in soft light as they tip and break. The look runs through ASMR channels, toy marketing and loops made to be watched more than once.
Make a 10-second satisfying macro film of kinetic sand: a striped block is sliced slowly, the slices tip over and crumble softly, and a last diagonal cut sends a wedge sliding down its own striped face. <inputs> If I don't give you something, use the default and don't ask. - Brand: Crumbwell Sand Co. (fictional). - Title: "Slow cut" - Line: "Five layers, packed by hand. 860 g of sand that moves." - Layers, bottom to top: moss, terracotta, bone, mustard, ultramarine. - Length: 10 seconds. </inputs> <direction> - Look: an oddly satisfying macro, shot like a food commercial: soft overhead light, a striped block of fine sand on an oak board in front of a dusty-rose sweep, every cut face crisp and velvety, every edge just about to crumble. - Palette: sweep #E6C1BB lifting to #F1D6D1 behind; oak board #D5B38B with grain #B8916A; sand layers moss #627C3E, terracotta #C65A3B, bone #EDE3CF, mustard #DCA43A, ultramarine #3550C4; blade steel #C9CDD2 with a walnut handle #5A3A28; contact shadows warm #8A5A50, never grey; type #3A1F1C, secondary #7A4F48, accent ultramarine. The ultramarine top layer is the one cool note against rose, oak and the earth tones beneath it. - The block (1 unit = 1 cm): 12 long × 6 deep × 7.5 tall, five layers 1.5 thick, their boundaries gently wavy (±0.12, seeded low-frequency noise) like hand-packed sand; the top slightly domed and pocked; the outer edges softly crumbled (seeded vertex noise 0.08), never sharp. - The sand material: color is a function of object-space position (layer height plus the boundary waviness), computed in the shader through onBeforeCompile, so every cut face shows the stripes exactly where they would be. Grain: a fine 3D speckle at about 0.02 per grain (±6% value per grain, a few mica points 2% brighter) with a matching micro-normal. Outer surfaces: MeshStandardMaterial, roughness 0.95, with a lumpy normal. Cut faces: smoother (roughness 0.75) with a soft velvet sheen (MeshPhysicalMaterial sheen 0.6, sheenColor the layer color lifted 20%), so a fresh cut reads compressed and smooth. Each slice is its own mesh in the block's material and object space. - The blade: a long thin steel knife, 24 × 3.6 × 0.08 with a slight taper, its walnut handle off frame to the right, MeshPhysicalMaterial metalness 1, roughness 0.18, carrying a long softbox highlight; after each cut a dusting of grains in the layer colors clings to its lower edge. - Cutting, closed form: the blade descends vertically at 8.5 cm/s (slow enough to savor), pressing the top down 0.1 and pushing a small bulge of grains up on both sides of its edge as it enters; behind it the cut face is exposed; at the board it pauses 0.1 s, then its flat nudges the top of the slice outward, just past balance, and it lifts away. - Tipping, precomputed once at load at a fixed 1/600 s step: a slice of height h and thickness w pivots about its bottom outer edge, θ'' = (3g ÷ (2·√(h² + w²)))·sin(θ − β) with tan β = w ÷ h and g = 981 cm/s², starting 3° past its balance angle β, where the blade's nudge leaves it. Slice 1 falls flat onto the board, cut face up, squashes 4% in thickness, springs back once, and breaks into three chunks along two seeded curved cracks (pre-split geometry: ExtrudeGeometry from the slice outline divided by the crack curves) that slide apart 0.2–0.6 and stop. Each later slice tips until it rests against the slice before it: at load, rotate its 2D outline about its pivot until it first touches the previous slice's resting outline, so the slices end up shingled like fallen books, cut faces up, and they never pass through each other or the board. - The diagonal cut: the blade tilts to 50° and cuts down through the rest of the block from its top right edge to the board on the left. The upper wedge then slides down the cut on friction, s = ½·g·(sin 50° − μ·cos 50°)·τ² with μ = 1.12, slow and heavy, easing to rest as its lower edge meets the board, and leaves a large slanted face on the block whose stripes run across it at an angle. - Crumbs and grains: each landing breaks 30–60 crumbs (rounded clumps 0.15–0.4 across, in that edge's layer colors) off the leading edge, which roll and settle on ballistic paths with friction; a soft trickle of fine grains (0.03–0.06) slides down each fresh cut face for 0.4 s after the blade passes; a few hundred loose grains lie on the board from the start. - Light, soft and bright from the first frame: a large overhead softbox (RectAreaLight 30 × 20, intensity 4, with RectAreaLightUniformsLib) slightly in front of the block; a key DirectionalLight #FFF3EA at 1.6 from the upper left (elevation 60°) with soft shadows (PCFSoftShadowMap, 2048, radius 4); a HemisphereLight #FFF1EC / #B98E86 at 0.9; under every piece a soft contact shadow (a blurred ellipse, #8A5A50 at 35%). ACESFilmic, exposure 1.05. Every layer color reads clearly on the cut faces, the ultramarine included. - Camera: fov 28, a macro three-quarter view from the front left, 30° above the board, the block centered at (980, 600) and about 760px wide at the start; across the piece it pulls back 8% and tracks right as the slices fall, so the final frame holds the wedge at left, the slanted block at center and the shingled slices at right, all between x 260 and 1800 and below y 380; no shake. - Type (HTML over the canvas): kicker "CRUMBWELL SAND CO." in Urbanist 700, 20px, tracked 0.18em, accent; title Urbanist 800, 104px, #3A1F1C, top-left at (120, 110); line Urbanist 500, 28px, secondary, beneath; a counter at bottom-left (120, 1000), "Cuts 0/4", in Urbanist 600, 26px, tabular figures. Text rises 12px as it fades in over 0.5 s on cubic-bezier(0.22, 1, 0.36, 1). - Premium: velvety cut faces striped exactly, edges that crumble, slices that tip with weight and land softly, grains that trickle. Cheap: plastic-looking striped boxes, slices that swing on a hinge and stop dead, crumbs that are cubes. Banned: hands, glossy or plastic sand, perfectly sharp box edges, stripes that don't line up across a cut, slices passing through the board or each other, sparkles or glitter, bloom, motion blur, anything flashing more than 3 times per second. </direction> <structure> - 0.0–0.6s: the whole striped block on the board, loose grains around it; the kicker and title rise in. - 0.6–2.1s: cut 1, 1.4 thick, at the right end: the blade sinks through and lifts away; the slice tips, lands flat and breaks into three chunks with a scatter of crumbs. - 1.85–3.3s: cut 2, 1.4 thick: the slice tips and comes to rest leaning on the first. - 3.1–4.5s: cut 3, 1.6 thick: it tips and leans on the second; grains trickle down its face. - 4.25–4.45s: the blade lifts and tilts to 50°. - 4.45–5.3s: cut 4: the blade cuts diagonally down through the rest of the block and lifts out of frame. - 5.3–5.85s: the wedge slides slowly down the cut and settles on the board at left. At 6.0 s: the wedge at left, the slanted striped face at center, three shingled slices and the broken chunks at right, the blade gone, everything still. - 6.0–7.4s: the last crumbs settle and a final trickle runs down the slanted face; the camera eases to its final framing. - 7.4–8.2s: the line rises in. - 8.2–10.0s: hold. For other lengths, add or remove slices at the same 1.25 s spacing; keep the diagonal cut and at least 1 s of hold. </structure> <build> - One self-contained index.html (inline CSS and JS), a 1920×1080 (16:9) stage scaled to fit the window, designed for 60fps. No image, video, texture or model files: every shape and texture is generated in code. - window.seek(t), t in seconds, computes every visual from t alone: no CSS transitions or CSS animations, no setTimeout/setInterval, no state carried between frames, randomness only from a seeded PRNG. Anything cumulative is solved analytically from t or precomputed once at load at a fixed step. Past the end, seek clamps to the last frame. - Without ?render in the URL, drive seek from requestAnimationFrame so it plays in a browser (loop after a 1s end hold); with ?render, don't start that loop. - Google Fonts via <link> are fine; await document.fonts.load() for each face before defining window.seek. - Engine: three.js as an ES module pinned to three@0.160.0 through an import map on jsDelivr (`three` and `three/addons/`). WebGLRenderer with antialias, preserveDrawingBuffer: true and setPixelRatio(window.devicePixelRatio); render once at the end of every seek. Text is HTML over the canvas. - Blade positions, cut depths and the wedge's slide are closed-form functions of t; tipping angles, resting contacts and every crumb's path are precomputed once at load at a fixed step and only read in seek. Build the slice and chunk geometry once at load; the counter reads the cuts finished by t. </build> <check> Before showing me, step through one frame per second (t = 0…10): screenshot each and look at it. Fix overlaps, clipped or cramped text, and anything off-style or Banned. Check the stripes line up across every cut and every chunk, each slice tips with weight and lands softly (no hinge-stop), the shingled slices rest on each other without interpenetrating, the crumbs settle and stay put, the cut faces read velvety and every layer color stays clear, the wedge slides down its cut without lifting off or sinking in, the counter matches the cuts, the 6.0 s frame is complete with the blade out of frame, and contact shadows are soft and warm. Confirm seek(10) and seek(11) match, so the final frame holds. </check>
Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.
A slow golden-hour glide down a faceted valley: flat-shaded ridges, a low sun, fog melting the far range into the horiz…
A device built in three.js rises out of total darkness while a softbox reflection glides along its titanium edge, then…
A toy-like isometric city block that builds itself on a floating slab: bevelled buildings rise floor by floor, cars loo…
Chunky two-tone 3D letters swing into place one by one on a seamless studio sweep, lit like a product shot with soft sh…
More like this on the motion design inspiration board: 3D motion design inspiration