AI CSS Animations

Lenticular Flip

A lenticular postcard tilts over a coral sweep under a strip light: its ridged plastic shimmers with fine highlight lines as the picture flips between a sunny lighthouse and the same coast at night, and a macro move shows the ridges, the scalloped edge and bands of interlaced stripes.

Written and rendered by AI CSS Animations Oct 19, 2026

Type
prompt
Made with
Claude Opus 5.5 in Claude Code
Built in
three.js
Topics
3D · 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 lenticular print lays a sheet of tiny parallel cylindrical lenses over an image made of thin interlaced strips, so each lens shows a different strip depending on the angle it is seen from. With two images interlaced, tilting the print flips between them; with many, it can show motion or depth. Lenticular cards became popular in the mid-20th century as novelty postcards, prizes and advertising giveaways, and the technique is still used for packaging, book covers and posters.

The prompt

Make a 10-second macro product film of a lenticular postcard: the ridged plastic card tilts under a strip light and flips between a day picture and a night picture, and the camera moves close enough to see its ridges and interlaced stripes.

<inputs>
If I don't give you something, use the default and don't ask.
- Maker: Ambrel Card Co. (fictional)
- Picture A, day: "Greetings from Port Ambrel" over a red-banded lighthouse on a green headland, a white sailboat, gulls and summer cumulus.
- Picture B, night: "Wish you were here!" over the same headland at night: the lighthouse lit with its beam, a crescent moon, stars and warm cottage windows.
- Title: "Two pictures, one card."
- Line: "Lenticular postcard · 40 lines per inch"
- Length: 10 seconds.
</inputs>

<direction>
- Look: a macro product film of a real lenticular postcard: a sheet of clear ridged plastic laminated over an interlaced print, tilting under a long strip light. Its surface carries a fine corduroy of highlight lines, a bright band slides across it as it tilts, and the picture changes from day to night in a band that sweeps across the card with a brief ghost.
- Palette: a backdrop sweep in coral, #E06A4C at the floor rising to #F2936E behind; shadows deep terracotta #8F3524, never grey; the card's white print layer #F7F4EE and the clear lens layer's cut edge pale aqua #DDEFEA. Picture A: sky #4FA3E0 to #BFE3F5, sea #2F7FB8, grass #6DB24A, lighthouse cream #F4EBD8 with red bands #D2382B, white cottages with slate roofs #4F5B6E, sail #FFFFFF, script #FFFFFF with a #1E4E8C drop shadow. Picture B: sky #0E1A3A to #26325F, sea #142850 with a moon path #E8E2C4, grass #23402E, lantern #FFE3A0 with a beam #FFF2C8 at 40%, windows #FFC86A, stars #FFF6DA, script #FFE7A8 with a #0B1430 drop shadow. HTML type #2B1410 and #6E2C1C.
- The card (1 unit = 10 cm): 1.48 × 1.0 and 0.006 thick with corners rounded at 0.03: a printed layer under a clear lens layer 0.004 thick. Its cut edges are real geometry: along the left and right edges, where the ridges end, the lens layer's profile is a row of semicircular scallops sitting on the white print layer. Lenticules run horizontally at 40 per inch, a pitch of 0.00635 units: about 5px on screen in the wide view and about 60px in the macro.
- The pictures: two CanvasTextures, 2048 × 1384, drawn after the fonts load as printed souvenir postcards: crisp illustrated shapes inside a white 40px border, the script across the sky in Lobster 400 (A: "Greetings from" at 70px over "Port Ambrel" at 160px; B: "Wish you were here!" at 150px in the same place). The headland, lighthouse, cottages and sea line up exactly in both, so only light, sky and words change.
- The lens, in a ShaderMaterial on the card's front face, per fragment:
  - lenticule index i = floor(y_card / pitch) and position across it u = fract(y_card / pitch);
  - the view angle φ between the view ray and the card normal, measured in the card's local y–z plane, refracted into the plastic (n = 1.56): sin φᵣ = sin φ ÷ 1.56;
  - pitch correction, as real printers do: the strips are calibrated for a viewer straight in front of the card at D_cal, 80% of the hero camera's distance. For each fragment, φ_cal is the refracted angle at which that calibrated viewer would see it (from tan φ = y_card ÷ D_cal, with the sign that makes φᵣ − φ_cal equal the card's tilt everywhere for that viewer);
  - selection: s = fract(0.5 + 3.0·(tan φᵣ − tan φ_cal)); the lens shows A where s < 0.5 and B otherwise, blended over ±0.04 at each boundary, and always lets 6% of the other picture through as ghosting. One full A–B cycle takes about 30° of tilt: A from about −15° to 0°, B from 0° to +15°. From the hero view the card shows one picture, and because a little spread remains, a flip crosses it as a quick band; in the macro, far from D_cal, the angle changes fast from ridge to ridge and several bands of A and B lie across the surface at once;
  - each lenticule shows one row of the print: sample the picture at its center row, v = (i + 0.5)·pitch, so up close the picture breaks into horizontal stripes of flat color, exactly as under a real lens, while along x it stays sharp;
  - the ridges: each lenticule is a cylindrical lens, so its normal tilts across u from −38° to +38° about the ridge axis. With that normal, compute a GGX specular (roughness 0.12) from the strip light's direction (a uniform that matches the scene light) and from the PMREM environment, plus 12% darkening in the valleys between ridges: one thin highlight line per ridge, gathering into a bright band where the strip light reflects;
  - antialiasing: where a ridge spans less than 3px (from fwidth of u), fade the per-ridge highlight lines and valley darkening to their average, so the surface never moirés or shimmers at a distance.
- Light: a long strip softbox above and to the left (RectAreaLight 4 × 0.6, #FFFFFF, intensity 8, with RectAreaLightUniformsLib), the source of the sliding sheen band; a key DirectionalLight #FFF4E6 at 1.8 from the upper left with soft shadows (PCFSoftShadowMap, 2048), so the card casts a soft terracotta shadow on the sweep; a HemisphereLight #FFF1E8 / #C2553A at 0.8; an environment baked once with PMREMGenerator.fromScene from a small room holding the strip and two dim side panels. ACESFilmic, exposure 1.05. Both pictures read at full brightness from the first frame, and the night picture stays legible.
- The card floats 0.5 units above the sweep floor, tilting about its horizontal axis (pitch) and turning slowly (yaw) on closed-form curves of t, solved so the flips at the card's center land at the times below. Never more than two flips in any one second.
- Camera: fov 30. The hero view holds the card about 1150px wide, centered at (960, 520). The macro: fov 18, 0.22 units from the card's lower-right corner, grazing at 35°, with the scalloped right edge running down the right side of the frame and the ridges reading as glossy rods. Moves run on cubic-bezier(0.45, 0, 0.2, 1).
- Type (HTML over the canvas): a kicker "AMBREL CARD CO." in Work Sans 600, 20px, tracked 0.18em, #6E2C1C, at (120, 96); the title in Fraunces 600, 72px, #2B1410, in two lines, top-left at (120, 130); the line in Work Sans 500, 26px, #6E2C1C, beneath it. In the final frame the card sits right of the type, centered at (1210, 560) and about 1000px wide.
- Premium: plastic that reads as ridged plastic (fine corduroy highlights and a sliding band), a flip that sweeps across the card with a ghost, stripes you can count up close, a scalloped cut edge, a soft colored shadow. Cheap: a crossfade between two flat images on a rectangle, no ridges, a flip that happens everywhere at once.
Banned: plain crossfades, holographic rainbow foil, glitter, real places or brands, photos, bloom, motion blur, moiré or shimmer on the ridges, more than two flips in any second, anything flashing more than 3 times per second.
</direction>

<structure>
- 0.0–1.2s: the hero view: the card floats over the coral sweep showing the day picture, tilting slowly toward the light as the highlight band slides across its ridges.
- 1.2–3.0s: it tilts through the flip angle and back: day to night at 1.6 s and night to day at 2.6 s, each flip sweeping across the card as a band in about 0.2 s with a soft ghost.
- 3.0–5.2s: the camera moves in to the macro at the lower-right corner: ridges as glossy rods, the scalloped right edge in profile, the picture broken into stripes; as the card tilts slowly, bands of day and night stripes sweep across the surface, the angle differing from ridge to ridge up close.
- 5.2–6.0s: the camera pulls back to the hero view as the card settles on the night picture; at 6.0 s the whole night card fills the view, with no band mid-card.
- 6.0–7.6s: one slow turn: the card yaws 25° and pitches back through the flip to the day picture (7.0 s) while easing toward its final place at the right.
- 7.6–8.6s: the kicker, title and line rise 12px as they fade in at the left, 0.15 s apart, on cubic-bezier(0.22, 1, 0.36, 1).
- 8.6–10.0s: hold on the day card, the highlight band resting in its upper third.
For other lengths, stretch the macro beat; keep each flip's 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.
- The card's pitch and yaw, the camera path and every flip are closed-form functions of t; the lens is evaluated per fragment from the current view, so nothing about a flip is animated by hand. Draw both picture CanvasTextures once after the fonts load, with mipmaps and anisotropic filtering on.
</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 the ridges read as fine highlight lines at full view and as glossy rods with countable stripes in the macro, the flips sweep across the card as bands with a ghost and never cut everywhere at once, no frame shows moiré or shimmer, the scalloped edge is visible in the macro, both pictures line up so only light and words change, the card's shadow is soft terracotta, and the 6.0 s and final frames each show one clean picture. 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: 3D motion design inspirationMotion graphics inspiration