Bamboo painted in sumi ink on rice paper, stroke by stroke: stalk segments brushed upward with dry-brush streaks, dark nodes, quick branches, then leaves flicked in clusters from dense to pale ink, finished with a vermilion seal beside a small title.
Written and rendered by AI CSS Animations Oct 16, 2026
Ink-wash painting developed in China and reached Japan with Zen Buddhist monks around the 14th century, where it is known as sumi-e. It is painted with a soft brush and ink ground from a stick on an inkstone, and it prizes economy: each stroke is laid once without correction, and tone runs from dense black to pale grey by diluting the ink. Bamboo is one of the Four Gentlemen, with plum, orchid and chrysanthemum, the subjects traditionally used to teach the brush. The look endures in illustration, packaging and title design.
Make a 10-second sumi-e ink painting: bamboo stalks, branches and leaves brushed stroke by stroke on rice paper, finished with a red seal. <inputs> Title: Bamboo After Rain. Line: "Bends in the storm, stands after it." Studio: Kurohane Ink Studio. Seal character: 竹 (bamboo). Duration: 10s. If I don't give you something, use the default and don't ask. </inputs> <direction> Paper: rice paper #F2ECDF, generated once at load: soft mottling and a few hundred faint long fibers. Ink is one ink at three dilutions: dense #141210, mid (55%) and pale (25%), laid with 'multiply'. Composition: a front stalk in mid ink, 44px wide, rises from below the bottom edge at x 540 and leans right to leave the top edge at x 760; a back stalk in pale ink, 30px wide, rises from x 380 to a cut end at x 470, y 140. Leaves hang down and to the right after rain in three clusters: two dense front clusters on twigs from the upper nodes (around 820, 300 and 700, 520) and one pale cluster behind (around 520, 260). The right 40% stays empty paper apart from the text and seal. Stalks: segments 140–240px long, shortest at the base, each a single stroke brushed bottom to top: a little wider at the start and end (the stroke's bone), darker along both edges where ink pools, with dry-brush streaks opening through the middle toward the top. Leave a 10px gap between segments; each gap later gets a node, a short dark stroke like a flattened bracket, wider than the stalk. Branches: thin, quick strokes (6–10px) from the nodes, with small knuckles. Leaves: each one press-and-lift stroke 140–220px long: it starts light and narrow, swells to full width (24–34px) about a third along, then tapers to a sharp tip. Group them in threes to fives fanning from a twig end, overlapping like the classic 个 and 介 groupings; front leaves in dense ink, back leaves pale for depth. Brush model: 28 bristles across the stroke. Each bristle lays its own track of small overlapping ellipses along the path, with an ink load that depletes along the stroke; where a bristle runs dry it skips, opening the white streaks of kasure. Width, pressure and ink load follow per-stroke curves. Wet starts bleed 2–3px into the paper (a soft 15% halo). A stroke lands 8% darker and dries to its final tone over 1.5s. Type, #1C1A17, left-aligned at x 1320: Zen Old Mincho 600, 54px, for the title (baseline 680); Zen Old Mincho 400, 28px, for the line (baseline 730); 22px, tracking 0.12em, for the studio (baseline 790). The seal: a 72px vermilion #B32D2A square at x 1320, y 840, the character reversed out in Zen Old Mincho 900, edges slightly ragged, ink faintly uneven. Motion is decisive: each stroke is one confident gesture at its own speed (stalk segments 0.32s, leaves 0.16–0.24s, branches 0.12s) on cubic-bezier(0.3, 0, 0.2, 1), so the brush starts deliberately and flicks off, with a 60–100ms lift between strokes. Paint in the painter's order: stalks, nodes, branches, then leaves front to back. The real thing is economy: every stroke laid once, tone and dryness doing the shading. The cheap version is vector leaves under a brush texture, or a bamboo clip-art silhouette. Banned: outlines around leaves, uniform stroke widths, flat vector fills, an ensō, cherry blossoms, moons or red suns, brush fonts for Latin text, a second seal, any color besides ink and vermilion, anything flashing more than 3 times per second. </direction> <structure> 0.0–0.6s: paper alone. 0.6–2.8s: the front stalk, six segments brushed bottom to top. 2.8–3.5s: the back stalk in pale ink, four quicker segments. 3.5–4.1s: nodes on both stalks, bottom to top, 50ms apart. 4.1–4.7s: branches from the upper nodes. 4.7–7.2s: leaves: the lower front cluster (5), the upper front cluster (4), then the pale back cluster (4), with a 0.2s pause between clusters. 7.2–8.0s: title, line and studio appear line by line (0.5s each, 0.15s apart) with a 4px blur-to-sharp ink bleed. 8.0–8.3s: the seal presses in: scale 1.05 → 1 and full ink in 0.2s. 8.3–10.0s: hold; the last strokes finish drying by 8.8s, then nothing changes. For other durations, keep stroke speeds fixed and scale the pauses and holds. </structure> <build> One self-contained index.html, CSS and JS inline. Google Fonts via <link> are fine; await document.fonts.load() for each face before defining window.seek. No other libraries (no three.js: this style is flat). Draw in Canvas 2D, repainting every frame from scratch, with the backing store sized from the canvas's CSS size × devicePixelRatio. Canvas won't fetch fonts itself, so the font wait matters. At load, precompute every stroke's stamps from the seeded PRNG and render each finished stroke once into its own offscreen canvas; seek(t) draws finished strokes as images and stamps only the stroke in progress. The stage is 1920×1080 (16:9), scaled to fit the window. Design for 60fps. window.seek(t), t in seconds, must compute every visual from t alone, clamping past the end to the last frame: no CSS transitions or animations, no setTimeout or setInterval, no state carried between frames, and randomness only from a seeded PRNG. Anything cumulative is precomputed once at load from the seeded PRNG at a fixed step, or solved analytically, so seek(t) can jump to any time. 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. </build> <check> Before showing me, step through one frame per second: screenshot each and look at it. Fix overlaps, clipped or cramped text, accidental edge collisions, and anything off-style or Banned. Check strokes show pressure and kasure rather than uniform ribbons, leaves taper to sharp tips, back leaves read paler and behind, at least 40% of the frame is empty paper, and no two strokes look identical. Confirm seek(duration) and seek(duration + 1) match, so the final frame holds. </check>
Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.
A cyanotype-blue engineering sheet that drafts itself: centerlines, compass-swept gears, hatching and dimension lines a…
A symmetrical Art Deco reveal in black and metallic gold: a sunburst fans open, stepped pinstripe frames draw from the…
A black-and-white Op Art piece: crisp stripes swell into a bulging lens and slow waves, and the title exists only as a…
A quiet Japanese minimalist piece on generated washi paper: a single sumi ensō is brushed on with dry-brush texture, sm…
More like this on the motion design inspiration board: Line art animation inspiration