Against a putty-colored studio sweep, six jets of powder, pink, turmeric yellow, blue, orange, green and violet, rise in slow motion and open into billowing clouds with grainy leading edges, collide and blend into coral and teal where they mix, then sink and dust the floor.
Written and rendered by AI CSS Animations Oct 19, 2026
Holi is a Hindu spring festival held on the full-moon day of the month of Phalguna, usually in March, when people throw and smear colored powder, called gulal, on friends and strangers alike. It celebrates the arrival of spring and the victory of good over evil, and begins the night before with the bonfire of Holika Dahan. The colors were once made from plants such as tesu flowers and turmeric, and many makers are returning to them. Filmed at high frame rates, a throw of powder opens into billowing, layered clouds, a look now used in advertising, sports films and color runs.
Make a 10-second high-speed film of colored powder: six jets of vivid powder rise and open in slow motion against a clean studio sweep, billowing, colliding and mixing in the air, then drift down to settle. <inputs> If I don't give you something, use the default and don't ask. - Brand: Palashri (fictional), makers of plant-based Holi colors. - Title: "Thrown into spring" - Line: "Six colors from flowers, leaves and roots." - Chip: "1,000 fps · 1/33 speed" - Colors, in order: Gulabi pink, Haldi yellow, Neel blue, Tesu orange, Hara green, Jamuni violet. - Length: 10 seconds. </inputs> <direction> - Look: a premium high-speed studio shot. Dense powder clouds with crisp, grainy leading edges and soft billowing insides, lit by a big softbox so each cloud has a lit side, a deeper core and a bright rim, against a seamless sweep. Calm, continuous slow motion. - Palette: sweep putty #E8E2D8 on the floor curving up to #F2EEE7 behind, with a soft #FAF7F2 lift behind the clouds; gulabi #EC1C84, haldi #FFC81E, neel #1466D6, tesu #FF7A12, hara #22A447, jamuni #7A3CC8; cores up to 35% deeper in the same hue, never grey or black; rims lifted toward white by the backlight; type #2B2430, secondary #6E6474. - How the colors interact: where clouds interpenetrate, grains mix and the eye reads the blend (pink into yellow reads coral, blue into yellow reads green-teal, pink into blue reads violet), while thick regions simply hide what is behind them; nothing is additive, so overlaps never go white; each cloud throws a soft shadow of its own hue onto the floor, and the dust that settles stains the floor in its colors. - The six throws: each is a jet of powder rising into frame from below the floor line at a seeded angle (10–30° from vertical), decelerating hard under drag, its head rolling over into a turbulent cap that opens into a cloud 500–800px across, then spreading slowly and sinking. Launch positions and leans: gulabi from x 920 leaning right; haldi from x 1520 leaning left; neel from x 760, low, toward the right; tesu from x 1280, rising high; hara from x 1660, low, toward the left; jamuni from x 1080, straight up. The clouds live between x 640 and 1800 and above y 820. - Particles, all closed-form from seeded constants, never stepped: each throw has 12,000 puffs and 6,000 grains. A particle's position is its launch point plus the jet path under exponential drag, p = p₀ + (v₀/k)(1 − e^(−kτ)) (k 2.5–4.0 in screen time), plus a radial spread from the cap's center that grows as S·(1 − e^(−τ/0.9)), plus a roll about the cap's horizontal ring axis that slows as e^(−τ/1.4), plus turbulence from seeded sums of sines whose amplitude grows as 1 − e^(−τ/1.2), plus a gentle sink once the jet has stalled. Grains ride the leading edge, thrown 5–15% ahead of it in fine streams, then fall in slow arcs. - Drawing: puffs are THREE.Points with a ShaderMaterial, each a soft sprite 18–70px whose alpha is cut by its own rotated noise, so edges are wispy rather than round, at 0.05–0.16 opacity with normal alpha blending, sorted back to front every seek. Grains are a second Points layer, 1.2–2.5px, 60–90% opaque and crisp. Shade every puff in the shader: lit or shaded by its offset from its cloud's center along the softbox direction (upper left), darkened by its depth into the cloud along that direction (e^(−depth)), and given a rim lift from a strip light behind at the upper right where its offset is perpendicular to the view. Every color keeps its hue in shadow. - Floor and light: the sweep is a curved mesh (MeshStandardMaterial, roughness 0.9) lit by a HemisphereLight #FFFFFF / #E1D9CC at 1.1 and a soft DirectionalLight from the upper left, bright from the first frame. Under each cloud a soft shadow in its hue, up to 18%, grows as it spreads; grains that reach the floor stop where they land and stay as fine colored dust, with a faint stain building under them. - Camera: fov 32, just above floor level, so the floor line sits at y 820 and curves up behind, with a slow 4% push-in across the piece. No depth-of-field pass and no shake. - Type (HTML over the canvas): title Mukta 800, 88px, #2B2430, two lines, top-left at (120, 110); line Mukta 400, 26px, secondary, beneath it; the chip in Fragment Mono 400, 20px, secondary, right-aligned at (1800, 96); a color legend in the left column from (120, 470), six rows 44px apart, each a 16px dot in its color and its name in Mukta 600, 22px, appearing as its throw opens. Everything stays left of x 600. Text rises 12px as it fades in over 0.5 s on cubic-bezier(0.22, 1, 0.36, 1). - Premium: dense, wispy powder with grainy edges, billows that roll over, a lit side and a deeper core, colors that blend where they mix and hide where they're thick, in calm slow motion. Cheap: round blurred blobs swelling at constant speed, additive neon glows that turn white where they overlap. Banned: additive blending, round blob sprites, neon or glow, bloom, dark backdrops, hands, people or faces, deities or religious imagery, smoke canisters, sparkles, rainbow gradients, sudden pops, anything flashing more than 3 times per second. </direction> <structure> - 0.0–0.6s: the clean sweep; the title rises in and the chip appears. - 0.6–1.8s: gulabi rises at center left, its head rolls into a cap and opens, grains streaming ahead. - 1.4–2.6s: haldi rises from the right and opens into the pink's edge, coral where they mix. - 2.4–3.6s: neel crosses low from the left, under the pink. - 3.2–4.4s: tesu rises high at center right. - 4.0–5.4s: hara rises low at the right; jamuni rises straight up the middle at 4.6 s. - 5.4–6.6s: all six roll into one layered mass across x 640–1800 (the 6.0 s frame: every color visible, crisp grain edges, nothing over the type). - 6.6–8.4s: the mass slows, spreads and sinks; grains fall like fine rain and dust the floor; the line rises in at 7.2 s. - 8.4–10.0s: hold: the clouds have all but stopped and drift by only a few pixels. For other lengths, change the gaps between throws; keep each throw's own timing 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. - Every particle is a closed-form function of t and its seeded launch data, generated once at load (keep load under 8 s); each seek writes positions into the Points buffers and sorts the puffs by depth. </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 every frame reads as powder (wispy edges, fine grains, rolling billows), never as round blobs; overlaps never turn white; every color keeps its hue in shadow; the clouds stay right of x 600 and off the title; floor dust appears only where grains have landed; the motion is slow and continuous with no pops; the sweep is bright from the first frame; the 6.0 s frame shows all six colors. 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.
Thousands of fine particles ride a curl-noise current, gather into a word or logo like a living engraving, dissolve bac…
A deep starfield stretches into blue-white streaks around one vanishing point, merges into a rolling tunnel of light, t…
Shells climb from harbor barges and burst into peonies, chrysanthemums, rings, palms and a finale of drooping gold will…
Thousands of starlings flow across a peach and mauve dusk sky as one mass, darkening into bands as the flock turns, par…
More like this on the motion design inspiration board: Particle animation inspiration