AI CSS Animations

Double Pendulum

On a mustard science plate, 48 double pendulums released 0.0002° apart swing and flip as one ink pendulum, then a colored fringe opens at the lower bob and they peel apart into a spray of navy-to-wine trails while a strip of marks scatters and the spread counter climbs.

Written and rendered by AI CSS Animations Oct 19, 2026

Type
prompt
Made with
Claude Opus 5.5 in Claude Code
Built in
Canvas
Topics
Explainer · Line art
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 double pendulum is one pendulum hung from the end of another, and its equations of motion follow from Lagrangian mechanics. At low energy it swings regularly, but released high it becomes chaotic: its motion is fully determined by the equations, yet the tiniest difference in starting angle grows exponentially until two runs share nothing. That sensitive dependence on initial conditions is the core idea of chaos theory, and the double pendulum is one of its simplest physical examples. Physics departments, science museums and explainer videos use it to show why long-range prediction fails.

The prompt

Make a 10-second explainer of chaos: 48 double pendulums released almost identically swing as one, then peel apart into a colored spray of trails, every motion from the exact equations.

<inputs>
If I don't give you something, use the default and don't ask.
- Title: "Almost the same start"
- Line: "48 double pendulums, released 0.0002° apart"
- Closing caption: "Same physics. Six seconds later, no two agree."
- Pendulums: 48, each two equal arms of 1 m with 1 kg bobs, released from rest at θ₁ = θ₂ = 135°, pendulum k (0–47) with θ₂ offset by (k − 23.5) × 0.0002°.
- Length: 10 seconds.
</inputs>

<direction>
- Palette, a printed science plate: ground mustard #E9B949 with a soft vignette to #DDA93A and a fixed 2% print grain; line work ink #1C1B2E; the 48 pendulums take colors along a ramp through navy #18224A, blue #2E5B8C, teal #2F8C83, cream #F4F1E6, vermilion #D2452F and wine #6B1F2A, in order of k; type #1C1B2E, secondary #5B4A22. Ink line work on a warm ground, with cool and hot trails that only separate when the chaos does.
- Physics, exact: angles from the downward vertical, counterclockwise positive; m₁ = m₂ = 1 kg, l₁ = l₂ = 1 m, g = 9.81 m/s²; with Δ = θ₁ − θ₂ and D = 2m₁ + m₂ − m₂·cos(2Δ):
  θ₁″ = [−g(2m₁ + m₂)·sin θ₁ − m₂·g·sin(θ₁ − 2θ₂) − 2·sin Δ·m₂·(θ₂′²·l₂ + θ₁′²·l₁·cos Δ)] ÷ (l₁·D)
  θ₂″ = [2·sin Δ·(θ₁′²·l₁·(m₁ + m₂) + g(m₁ + m₂)·cos θ₁ + θ₂′²·l₂·m₂·cos Δ)] ÷ (l₂·D)
  Integrate all 48 at load with RK4 at a fixed step of 1/2000 s, storing every 1/240 s; total energy must stay constant to better than 10⁻⁹ J. From these exact values the RMS spread of the lower bobs is about 1 cm 3.5 s after release, 7–14 cm at 4.25–4.75 s, about 0.2 m at 5.5 s, 0.7 m at 6.0 s and over 1 m from 6.3 s: one pendulum that becomes forty-eight.
- Time: release at t = 0.6 s; physical time τ = t − 0.6 until 8.0 s, then easing to a freeze over 8.0–8.8 s (τ advances at a speed falling on a half-cosine, a closed-form integral), so the last frame holds.
- Stage: the pivot at (1180, 520), 1 m = 215px, so the full reach of 430px stays inside y 90–950 and x 750–1610.
- Drawing: the pivot as a 14px ink ring on a short ink mount bar; each pendulum's two arms as 2px ink lines at 60% opacity (so the stack reads as one solid pendulum until it splits), an upper bob 10px and a lower bob 14px in its own color with a 1.5px ink outline. Each lower bob trails its path over the last 1.2 s as a line tapering from 2.5px to 0.5px and fading from 85% to 0, in its color, sampled from the stored states with Catmull–Rom; draw the pendulums in order of k.
- Phase strip, along y 990 from x 120 to 1800: a 1px ink baseline with ticks at −180°, −90°, 0°, 90° and 180°, and for every pendulum a 3 × 22px mark in its color at x set by its lower arm's angle θ₂ wrapped to ±180°. For the first seconds all 48 marks stack into one; then they scatter. Label "θ₂ of each lower arm" in Fira Code 400, 20px, secondary, above its left end.
- Readouts from (120, 640): "t" (seconds since release) and "Spread" (RMS distance of the lower bobs from their mean, in metres, two significant figures) in Fira Code 500, 30px, tabular figures, with labels in Rethink Sans 600, 20px, uppercase, tracked 0.12em, secondary.
- Type: the title in Rethink Sans 700, 76px, ink, at (120, 160), two lines at most; the line in Rethink Sans 500, 26px, secondary, beneath; the closing caption in Rethink Sans 600, 30px, ink, at (120, 880). Everything stays left of x 700 except the strip.
- Easing: text rises 12px as it fades in over 0.6 s on cubic-bezier(0.22, 1, 0.36, 1); nothing else is eased, because the motion is physics.
- Premium: the exact equations integrated with care, arms that never stretch, one pendulum that becomes forty-eight, trails that fan into a spray, an ink-on-mustard plate you could print. Cheap: random wiggles, glowing trails on black, pendulums at made-up speeds.
Banned: arms changing length, motion not from the equations, motion blur, glow or bloom, black backgrounds, rainbow hue sweeps, anything flashing more than 3 times per second.
</direction>

<structure>
- 0.0–0.6s: the stack held at 135°/135°, reading as one ink pendulum on the mustard plate; the title and line rise in.
- 0.6s: release.
- 0.6–4.1s: it swings and flips as one, its trails one stroke; the readouts and strip rise in at 1.2 s, the strip showing a single mark.
- 4.1–5.6s: a colored fringe opens around the lower bob and the strip's mark splits; the spread passes 10 cm.
- 5.6–8.0s: full divergence: 48 pendulums tumble on their own and the trails fan into a spray. The 6.0 s frame: the fan opening, colors separating, the arms still close together near the pivot.
- 8.0–8.8s: time eases to a freeze; the closing caption rises in.
- 8.8–10.0s: hold, completely still.
For other lengths, keep the physics and change only the hold before release and after the freeze; 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 2D, repainting every frame from scratch, the backing store sized from CSS size × devicePixelRatio. Canvas won't fetch fonts itself, so the awaited loads matter.
- All 48 pendulums are integrated once at load into Float32Arrays; seek(t) maps t to τ in closed form and only reads and interpolates the stored states.
</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. Also log the RMS spread at τ = 3.5, 4.5 and 6.0 s (about 0.01, 0.13 and 0.7 m) and the energy drift. Check the arms keep their length in every frame, the stack reads as one pendulum until about 4 s, the 6.0 s frame shows the fan opening, the strip marks match the lower arms, and the type stays clear of the pendulums. 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: Line art animation inspirationExplainer video inspiration