Top-down over a marbling tray: a whisk flicks ochre, indigo, madder and green drops that shove each other into stones, bullseyes bloom inside them, a stylus and a comb rake everything into fine nonpareil, then a sheet of paper lifts the print and turns over to show it.
Written and rendered by AI CSS Animations Oct 18, 2026
Marbling floats colors on a thickened bath, called size, and lifts them onto paper, so every sheet is a one-off print. In Turkish ebru, paints mixed with ox gall are dropped onto the size, where each new drop spreads and pushes the earlier colors into rings, and styluses and combs then drag them into patterns that marblers know by names such as stone, wave and nonpareil. Bookbinders across Europe used marbled sheets for endpapers and book edges, and UNESCO added ebru to its list of intangible cultural heritage in 2014. Designers still borrow the look for packaging, stationery and covers.
Make a 10-second paper marbling film, seen from above: paint drops spread on a bath, a stylus and a comb rake them into a marbled pattern, and a sheet of paper lifts the print. <inputs> If I don't give you something, use the default and don't ask. - Studio: Fenwright Bindery (fictional). - Title: "Each sheet happens once." - Caption: "Nonpareil on a stone ground · No. 31" - Paints: indigo, madder red, ochre, sea green and ivory. - Length: 10 seconds. </inputs> <direction> - Palette: walnut table #3A2A20 with a soft seeded grain; tray rim #6B4A33 with a lighter top edge #8A6347; size (the bath) #E6DCC3, faintly milky; paints indigo #22386E, madder #B3392E, ochre #D9A23A, sea green #2D6E66, ivory #F3EBD9; paper #F4EEE2; type on the table #F3EBD9 and #CDBFA6. - Layout, seen straight down: the tray's 28px wooden rim frames a bath at x 140–1780, y 110–840; below it a strip of table holds the title row. - The marbling model is exact and area-preserving: the pattern is a list of operations applied to the bath in order. Each pixel is colored by undoing every operation, newest first, then seeing which drop it lands in; if none, it shows the bath. Nothing is painted into a buffer, so any frame is direct to compute and paint never blurs. - Drop of radius r at c: paint outside it moves outward, p' = c + (p − c)·√(1 + r²/|p − c|²). To undo it for a pixel q: if |q − c| < r, the pixel is that drop's color; otherwise q ← c + (q − c)·√(1 − r²/|q − c|²). - Tine (one stylus stroke or comb tooth) along a line through L with unit direction m and unit normal n, displacement z and sharpness s: q' = q + z·u^d·m with d = |(q − L)·n| and u = 2^(−1/s). It shears along m, so d doesn't change and the undo is q ← q − z·u^d·m. Parallel teeth of one comb commute, so apply them as one combined shear. - Motion: a drop's radius grows to its full size over 0.35–0.6 s on easeOutCubic. A tool only drags paint it has passed: multiply z by a window W(σ) = 1 − smoothstep(σtool − w, σtool + 60, σ), σ being position along m, with w 400px for the stylus and 300px for the comb, and undo it with six fixed-point steps (q ← q' − z·u^d·W(σ(q))·m), which converge because each window is wider than its displacement. Finished operations apply at full strength. - The work, in order (about 122 drops and 38 tines, in uniform arrays or a small float texture): 1. stone ground: 110 drops (r 40–72px) flicked from a whisk at seeded positions, cycling ochre, indigo, madder and sea green, 15 ms apart, each new drop shoving its neighbors into a packed field of stones with thin bath-colored veins between; 2. three bullseyes: at three seeded centers, four drops each land inside the last (r 150, 115, 80 and 45px), ivory, indigo, madder, ochre; 3. a stylus rakes six horizontal passes 120px apart, alternating left and right, z 170px, s 36: the stones become waves; 4. a 32-tooth comb with pins 50px apart is drawn down the whole bath in one pass, z 80px, s 12: the waves break into fine nonpareil. - Paint surface: matte, flat and opaque with a 2% seeded grain; each drop keeps a 1px rim 8% darker where pigment piles at its edge, so stones read as stones. The bath has a faint sheen: a broad diagonal reflection of a window (12% lighter) that drifts slowly, and each landing drop sends one thin ring through the sheen only. - Tools, drawn in code and seen from above: the whisk as a bundle of 12 straw tips with a soft shadow, flicking over each cluster of drops; the stylus as a slim awl with a brass tip, its wooden handle leaning out of frame, shadow offset 12px; the comb as a wooden bar (#8A6142) spanning the bath with 32 steel pin heads, shadow offset 10px down-right. They enter and leave from off-stage. - The print: a sheet of paper (1560 × 680, deckled edges, fine fibers) slides in from the top with a wide soft shadow (30px blur), lowers onto the bath as its shadow tightens to 6px over 0.4 s, and the pattern shows through the wet paper at 20%. It lifts from the far edge, flips toward the camera (rotateX through 180° with perspective, 0.5 s) and settles back down, rotated −1° and offset 8px up and left: print side up, the pattern mirrored top to bottom as a sheet turned this way shows it, paper fiber faintly visible through the paint. The bath around it is left pale, its paint taken. - Type: title in Libre Caslon Display 400, 56px, #F3EBD9, baseline at (140, 975); caption in Libre Caslon Text italic, 26px, #CDBFA6, right-aligned at (1780, 975); the studio in Libre Caslon Text 400, 20px, tracked 0.2em, uppercase, #CDBFA6, right-aligned at (1780, 935). - Easing: tools travel on easeInOutSine; the sheet moves on cubic-bezier(0.45, 0, 0.2, 1) over 0.4–0.6 s; text rises 10px as it fades in over 0.6 s on cubic-bezier(0.22, 1, 0.36, 1). Nothing bounces. - Premium: paint that behaves (each drop pushes the earlier rings outward, a comb drags every color with it, edges stay crisp), real tools in frame, and the lift. Cheap: a swirl filter or noise warp over blobs, colors that smear into gradients or mud. Banned: blur or smudging, gradients inside paint, colors mixing into each other, noise-based warps or twirl filters, rainbow or neon colors, glitter, anything flashing more than 3 times per second. </direction> <structure> - 0.0–0.5s: the empty bath in its tray; the sheen drifts. - 0.5–2.2s: the whisk flicks the stone ground: 110 drops land across the bath, each pushing its neighbors aside. - 2.2–3.4s: the three bullseyes bloom, each drop landing inside the last. - 3.4–4.9s: the stylus rakes six passes, 0.25 s each, dragging the stones into waves. - 4.9–6.0s: the comb comes down the bath in one 0.9 s pass and lifts out: fine nonpareil across the whole tray. - 6.1–7.6s: the sheet slides in, lowers, wets through and lifts; it flips to show the print. - 7.6–8.4s: the print settles on the tray; the title row rises in. - 8.4–10.0s: hold. For other lengths, stretch the raking; keep 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: Canvas: one WebGL canvas (preserveDrawingBuffer: true, drawn once per seek), its backing store sized from CSS size × devicePixelRatio, whose fragment shader evaluates the operation list per pixel; the table, tray and tools on 2D canvases under and over it. The print is a second canvas rendered once at load with every operation at full strength and the pattern mirrored, multiplied with a paper texture, and moved with CSS 3D transforms set from seek. Type is HTML. - Every drop radius, tine displacement and tool position is a closed-form function of t; nothing accumulates between frames. </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 each new drop pushes the earlier paint outward with no overlap or blur, the comb drags every color with it, edges stay crisp at 1280×720, the print is the bath pattern mirrored top to bottom, the 6 s frame shows the finished combed pattern, and the title row sits clear on the table. 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 jazz-tempo film title sequence in flat vermilion, mustard, bone and black: hand-cut paper shards jab in on the beat,…
A Swiss-style event poster that builds itself on a visible 12-column grid: grotesque type rises out of baseline masks,…
A primary-colored circle, square and triangle roll, drop and turn into place on a black bar, assembling a constructed B…
A Constructivist poster in motion: red bars, a wedge piercing a black circle, halftone fields and condensed uppercase t…
More like this on the motion design inspiration board: Motion graphics inspiration