A white beam cuts through a dark studio, strikes a slowly turning glass prism and fans into a spectrum traced wavelength by wavelength, painting a band from red to violet across a charcoal floor before hairline labels and a quiet title settle in.
Written and rendered by AI CSS Animations Oct 16, 2026
Isaac Newton's prism experiments in the 1660s showed that white light is a mixture of colors, which glass separates because its refractive index is slightly higher for violet light than for red. That separation, called dispersion, is why a prism fans a beam into a spectrum with violet bent the most. A single beam entering a prism and leaving as a band of color has become a shorthand for light, science and clarity. Optics makers, science explainers and poster designers keep returning to it.
Make a 10-second glass prism film: a white beam strikes a slowly turning prism and fans into a spectrum that paints the floor. <inputs> - Brand: Aldane Optics. - Title: "Every color was already in the light." - Labels at the band's ends: "700 nm" and "400 nm". - Length: 10 seconds. If I don't give you something, use the default and don't ask. </inputs> <direction> Set: background #06070A; a matte charcoal floor #141519 lit only by the beams, melting into black. Text #EDEDEA, labels #8B8F99. Prism: equilateral, apex up, floating above the floor, long axis 20° off the camera axis, bevelled edges catching thin lines of light. MeshPhysicalMaterial: transmission 1, ior 1.7, thickness 1.2, roughness 0.02, lit by an environment baked once from a black room with two strip lights. Physics is the point: trace light through the cross-section with Snell's law at both faces, per wavelength, n(λ) = 1.62 + 32000/λ² (λ in nm; exaggerated so the fan reads): 48 rays from 400 to 700 nm, violet bent most, no total internal reflection. Color each ray from its wavelength (CIE approximation). Beams: a slit of light with a white core and soft halo, a pale wedge inside the glass, then 48 additive ribbons drawn after the glass, dimming with distance. The floor shader paints the band where rays land, red farthest from the prism. Seeded motes glint only inside beams. Camera: fov 32, 18° above the floor, pushing in 5%. Layout: prism near (820, 470); beam enters from the left edge near y 330; band from x 1120 to 1720 near y 800. Title at x 120, baseline y 960, Red Hat Display 400, 52px; brand above in Red Hat Display 500, 22px, uppercase, tracking 0.24em; labels in Red Hat Mono 400, 22px, on 1px leaders at the band's ends. Motion is slow and exact: the beam draws in over 0.6s on cubic-bezier(0.65, 0, 0.35, 1); the prism turns on one easeInOutSine curve and the fan moves only because of it; type rises 16px over 0.8s on cubic-bezier(0.22, 1, 0.36, 1). Premium is physics you could check: violet bent most, a fan widening with distance, one clean band in darkness. Cheap is a rainbow gradient and a lens flare. Banned: color not computed from wavelengths, red bending more than violet, lens flares, bloom, colored ambient light, anything flashing more than 3 times per second. </direction> <structure> - 0.0–1.0s: darkness; the prism's edges fade up as thin cool lines. - 1.0–1.8s: the white beam draws in from the left and strikes the left face. - 1.8–2.8s: the wedge crosses the glass; the fan leaves the right face and the band lights across the floor. - 2.8–6.2s: the prism turns −7° → +7° around minimum deviation; the band slides and breathes. - 6.2–7.2s: the prism eases to rest; leaders draw and labels fade in. - 7.2–8.4s: brand, then title 0.3s later, rise in at bottom-left. - 8.4–10s: hold; only the motes drift. Other lengths: scale the turn first; keep at least 1.2s of hold. </structure> <build> One self-contained index.html, inline CSS and JS, on a 1920×1080 (16:9) stage scaled to fit the window, built for 60fps. Google Fonts via <link>, awaited with document.fonts.load() before seek exists. window.seek(t) sets every visual from t alone: no CSS transitions or animations, no setTimeout/setInterval, no state carried between frames, randomness only from a seeded PRNG. The ray trace runs fresh in every seek from the prism's angle. Without ?render in the URL, drive seek from requestAnimationFrame; with ?render, don't start that loop. three.js as an ES module pinned to three@0.160.0 via a jsDelivr import map (`three`, `three/addons/`); preserveDrawingBuffer: true; one render per seek. No image, model or typeface files beyond Google Fonts. </build> <check> Before showing me, step through one frame per second (0–10s) and look at each. Fix overlaps, clipped or cramped text and anything off-style or Banned. Look for violet not landing nearest the prism, the band leaving the floor or frame, white-out where beams overlap, labels off the band's ends. Confirm 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