AI CSS Animations

Tessellation Morph

A two-ink woodcut tessellation: a plain checkerboard bends into interlocking birds and fish with no gaps, eyes, wings and scales carve in, then the birds on the right sink into dark water while the fish on the left fade into pale sky, figure and ground trading places.

Written and rendered by AI CSS Animations Oct 18, 2026

Type
prompt
Made with
Claude Opus 5.5 in Claude Code
Built in
SVG
Topics
Shapes
What Claude made from the prompt below in Claude Code: one HTML file rendered frame by frame to video. Silent preview.

About this style

A tessellation covers a plane with shapes that leave no gaps and never overlap. The Dutch printmaker M. C. Escher, after studying the tiled walls of the Alhambra in Granada, filled tessellations with recognizable creatures, and in woodcuts such as Sky and Water I (1938) let birds and fish swap roles as figure and ground. Every bump one tile gains is a dent its neighbor takes, which is what makes designing one a puzzle. Pattern designers, puzzle makers and math teachers still work this way.

The prompt

Make a 10-second two-ink woodcut tessellation: a plain checkerboard bends into interlocking birds and fish, and across the sheet the birds become water while the fish become sky.

<inputs>
If I don't give you something, use the default and don't ask.
- Title: "Wing and Fin"
- Line: "One plane, two creatures, no gaps."
- Edition: "Woodcut, two blocks · 7/40"
- Inks: Prussian blue on bone paper.
- Length: 10 seconds.
</inputs>

<direction>
- Palette: paper #F1E9DA with soft seeded fibers; ink #1D3557; pencil #6E675C. Two colors only, ink and paper. The print area is x 160–1760, y 90–850, with a faint plate mark (a slightly darker embossed line 14px outside it); the margin below holds the title row.
- The tiling, exact (derive everything from these numbers). Tile units map to screen as x = 960 + 150·X, y = 470 − 150·Y (Y points up).
  - Bird k (ink) sits at origin O = (2i, 1.24j) for integers i and j. Its corners: beak O + (−1, 0), wing tip O + (0.25, 0.62), tail O + (1, 0), lower wing tip O + (0.25, −0.62).
  - Four edge curves, each a uniform Catmull–Rom spline (end points repeated) through these points, relative to O:
    A, beak → wing tip: (−1, 0) (−0.9, 0.06) (−0.8, 0.15) (−0.68, 0.2) (−0.57, 0.17) (−0.48, 0.1) (−0.38, 0.12) (−0.28, 0.26) (−0.15, 0.42) (0.02, 0.55) (0.14, 0.61) (0.25, 0.62)
    B, wing tip → tail: (0.25, 0.62) (0.3, 0.45) (0.42, 0.5) (0.47, 0.32) (0.56, 0.2) (0.75, 0.14) (0.9, 0.08) (1, 0)
    C, lower wing tip → tail: (0.25, −0.62) (0.3, −0.45) (0.42, −0.5) (0.6, −0.33) (0.8, −0.16) (0.93, −0.06) (1, 0)
    D, beak → lower wing tip: (−1, 0) (−0.88, −0.05) (−0.74, −0.1) (−0.55, −0.2) (−0.32, −0.26) (−0.1, −0.32) (0.05, −0.42) (0.17, −0.55) (0.25, −0.62)
  - Bird outline: A, then B, then C reversed, then D reversed. It flies left: beak, round head, a raised wing swept back, a tapering tail.
  - Fish k (paper) fills the space above and right of bird k: C shifted by (0, 1.24), then D shifted by (2, 1.24), then A shifted by (2, 0) reversed, then B reversed. It swims right: snout at O + (2.25, 0.62), forked tail at O + (0.25, 0.62), dorsal fin tip at O + (1, 1.24), belly fin tip at O + (1, 0).
  - Every edge is shared by one bird and one fish, so the plane is covered with no gaps or overlaps. Fill birds and fish as paths with no outline strokes; the boundary between them is just the change of ink. Cover the print area with i from −4 to 4 and j from −3 to 3, clipped.
- From squares to creatures: at first every edge is the straight segment between its two corners, a checkerboard of slanted diamonds. Each edge then bends on its own morph value e from 0 to 1: every spline sample is lerp(the point at the same parameter on the straight segment, the curve point, e). Because e belongs to the edge, not the tile, both tiles that share it bend together and the tiling never opens. e = easeInOutCubic(clamp((t − 1.2 − 0.0011·(x + 0.35·y)) ÷ 0.9)), with (x, y) the edge's midpoint in px from the print's top-left, so a diagonal wave crosses the sheet from the upper left.
- Details, in tile units relative to O (stroke widths in px), drawn on with stroke-dashoffset over 0.35 s each:
  - Bird, carved in paper color: eye a 9px paper disc with a 4px ink pupil at (−0.7, 0.08); beak line (−1, 0) → (−0.86, 0.02), 2px; the wing root as a curve (−0.42, 0.13) → (−0.2, 0.2) → (0.05, 0.3) → (0.3, 0.36), 3px; three feather lines inside the wing, parallel to its leading edge, 2px; three tail lines converging on (0.98, 0); one line marking the far wing, (−0.2, −0.3) → (0.16, −0.48).
  - Fish, inked: eye a 10px ink disc with a 3px paper glint at (1.9, 0.68); mouth (2.25, 0.62) → (2.1, 0.58); a gill arc through (1.72, 0.92), (1.66, 0.75) and (1.7, 0.5), 3px; scales as small arcs bulging toward the tail, three rows at Y 0.45, 0.61 and 0.77, from X 0.75 to 1.5 every 0.18 (middle row offset 0.09), 1.6px; three rays in the tail fork; one ray in each of the dorsal and belly fins.
  - Every detail must sit inside its own tile; check each against the outlines.
- Figure and ground across the sheet, with g = a tile's center x mapped from 0 at x 160 to 1 at x 1760:
  - birds keep their carved details where g < 0.62 and lose them by g = 0.72, so on the right they become plain ink: water, crossed by fine horizontal gouge lines (broken paper-colored hairlines every 9px at 7%), as in a woodcut sea;
  - fish keep their inked details where g > 0.38 and lose them by g = 0.28, so on the left they become plain paper: sky;
  - in the middle third both read at once, each the background of the other.
- Print texture: the ink is not digitally flat: seeded speckle where paper shows through (3%), edges that wobble about 1px (an SVG feTurbulence + feDisplacementMap at scale 1.5 on the ink layer), and a slightly heavier ink density toward the bottom of each tile.
- Camera: a slow 1.00 → 1.04 push toward the sheet's center across the whole piece. Tiles never move or rotate on their own.
- Type: title in Marcellus 400, 52px, #1D3557, baseline at (160, 945); line in Outfit 300, 24px, #6E675C, baseline at (160, 990); edition in Outfit 400, 22px, tracked 0.06em, #6E675C, right-aligned at (1760, 945), like a pencil inscription under a print.
- Easing: text rises 10px as it fades in over 0.6 s on cubic-bezier(0.22, 1, 0.36, 1). Nothing bounces.
- Premium: shapes that lock with no gaps, a bird and a fish anyone can name at a glance, figure and ground trading places across one sheet, a surface that looks printed. Cheap: blob shapes, outlined stickers set side by side, gaps between tiles, a color gradient doing the work of the drawing.
Banned: gaps or overlaps between tiles, outline strokes around tiles, a third color, gradients, drop shadows, tiles moving or rotating independently, cartoon faces, anything flashing more than 3 times per second.
</direction>

<structure>
- 0.0–1.2s: bare paper; the plain checkerboard of slanted diamonds prints in from top to bottom, like a block taking ink under a roller.
- 1.2–4.1s: the bending wave crosses the sheet from the upper left: straight edges swell into beaks, wings, fins and tails until every tile is a bird or a fish.
- 4.1–5.4s: the details arrive: birds' eyes, wings and tails carve in sweeping left to right; fishes' eyes, gills and scales ink in sweeping right to left.
- 5.4–6.0s: figure and ground part ways: on the right the birds' details fade and gouge lines turn them to water; on the left the fishes' details fade and they become sky.
- 6.0–7.2s: the finished sheet rests while the push continues.
- 7.2–8.2s: the title, line and edition write into the margin.
- 8.2–10.0s: hold.
For other lengths, stretch the bending wave; 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: inline SVG. Every tile is a <path> whose d is rebuilt in seek from its four edges (16 samples per spline segment); details are stroked paths revealed with stroke-dasharray; the print area is clipped with a clipPath; paper fibers come from a canvas generated once at load, ink texture from SVG filters.
- Each edge's morph and each tile's detail and figure-ground state are closed-form functions of t and its position.
</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 at 4× zoom that no gap or sliver opens between tiles in any frame, every bird reads as a bird (beak, eye, raised wing, tail) and every fish as a fish (snout, eye, gill, forked tail), the left third reads as birds in a pale sky and the right third as fish in dark water, the 6 s frame and the final frame are both complete, and the margin type sits clear of the print. 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.

Similar prompts

More like this on the motion design inspiration board: Motion graphics inspiration