AI CSS Animations

Elastic Type

Lime letters on violet drop in and squash, then get grabbed and stretched like rubber: a stem pulled tall, a bowl dragged into a teardrop, the whole word pulled wide, thinning and whitening where stretched before snapping back with decaying overshoot.

Written and rendered by AI CSS Animations Oct 18, 2026

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

About this style

Squash and stretch heads the twelve principles of animation that Disney animators Ollie Johnston and Frank Thomas set out in their 1981 book The Illusion of Life. Elastic type applies it to letterforms: glyphs deform as if made of rubber and recover with springy overshoot, while the rest of the letter is dragged along behind the part being pulled. The recovery is usually modeled as a damped spring, the same math interface frameworks use for spring animations. It is a staple of social ads, app promos and playful brand campaigns.

The prompt

Make a 10-second elastic type piece: heavy letters are grabbed and stretched like rubber by an invisible hand, then snap back on springs with overshoot.

<inputs>
If I don't give you something, use the default and don't ask.
- Word: LIMBER (a fictional stretching app).
- Tagline: "Stretch a little every day."
- Details: New classes every Monday
- Length: 10 seconds.
</inputs>

<direction>
- Palette: ground violet #6B4BFF with a soft lift to #7B5EFF behind the word; letters lime #D6FF4A; their hard shadow deep violet #3A22B8; stretched-thin areas lighten toward #F1FFC2 like pulled rubber; small type #F4F0FF.
- Type: "Dela Gothic One" 400 for the word, cap height 300px, letters 28px apart, centered on x 960 with the baseline at y 640; "Space Grotesk" 500 for the tagline (44px, centered on baseline y 800) and 600 for the details (24px, tracked 0.14em, uppercase, centered on y 856).
- Rubber, not scaling: render each letter once at 2× into its own texture and draw it on a 96×96-segment plane mesh in WebGL. Each grab is an anchor point a on a letter and a drag vector D(t). A vertex at rest position p moves by D·w, with w = exp(−|p − a|²/2σ²) and σ 80–170px, so the grabbed region stretches most and the rest of the letter follows less. Keep the area roughly constant: near the stretch, pull the material in perpendicular to D by up to 30%, so a stretched stem gets thinner. Lighten the color by the local area stretch (from screen-space derivatives) toward #F1FFC2, up to 40%: the whitening of pulled rubber. Each letter's shadow is the same deformed mesh drawn in the shadow color 16px down and right, behind all the letters.
- Springs: while held, D eases out to its target over 0.4–0.5 s on cubic-bezier(0.2, 0.8, 0.2, 1). On release, D(s) = D₀·e^(−ζωs)·cos(ω_d·s) with ω = 2π·3.2 rad/s, ζ = 0.16 and ω_d = ω·√(1 − ζ²): about three visible overshoots, settled within 1.4 s. A letter struck by a neighbor's rebound takes a smaller impulse of its own (secondary action). Every response is computed from fixed grab and release times, so seek(t) is a pure function.
- Entrance: each letter falls from above the frame for 0.35 s with gravity-like acceleration, 70ms after the one before, squashes on the baseline to 1.25× wide and 0.78× tall, and springs upright on the same spring.
- Premium: material that thins and whitens as it stretches, the rest of the letter dragged along, overshoot that decays, a shadow that deforms with its letter. Cheap: CSS scaleX on whole letters, a uniform wobble, letters that bounce forever.
Banned: uniform scaling or skewing of whole letters, a visible cursor or hand, wobble that never settles, motion blur, glow, gradients beyond the stretch whitening, outlines, 3D, anything flashing more than 3 times per second.
</direction>

<structure>
- 0.0–1.0s: the violet ground; L, I, M, B, E and R drop in and squash onto the baseline one after another, springing upright.
- 1.0–2.0s: the top of the L's stem is grabbed and pulled up 280px, held 0.1 s and released at 1.55 s: it snaps back past rest, bobs and settles.
- 2.0–3.0s: the I is pinched at its middle and pulled 220px right into a thin bow leaning over the M; released at 2.6 s, it springs back and nudges the M, which wobbles a little.
- 3.0–4.0s: the B's lower bowl is pulled 240px down and right into a long teardrop, its counter stretching with it; released at 3.6 s, it rebounds and the E takes a small knock.
- 4.0–4.8s: both ends of the word are grabbed at once, the L's left edge and the R's leg, and pulled 200px outward; every letter stretches wider and thinner, whitening; released together at 4.6 s, the whole word jiggles.
- 5.0–5.8s: the tagline rises 14px out of a mask as the word comes to rest.
- 5.8–6.6s: stillness: word and tagline at rest, the 6 s frame fully settled.
- 6.6–7.6s: a last wink: the R's leg is tugged 120px down and let go at 7.0 s; it bounces twice; the details rise in.
- 7.6–8.8s: every spring settles.
- 8.8–10.0s: hold, perfectly still.
For other lengths, add or remove grabs at the same spacing; 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 building the letter textures and defining window.seek.
- Engine: Canvas: one WebGL canvas (preserveDrawingBuffer: true, drawn once per seek), the backing store sized from CSS size × devicePixelRatio, with each letter's texture built on an offscreen 2D canvas at load. Small type is HTML over the canvas. No libraries (no three.js).
- Grabs are a fixed table (letter, anchor, target, start, release); each seek sums every grab's closed-form D(t) per letter and passes them to the vertex shader as uniforms.
</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 stretched areas thin and whiten rather than scale, shadows deform with their letters, no stretch covers the tagline, LIMBER is fully at rest and readable at 6 s and through the final hold, and every spring has settled by 8.8 s. 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: Kinetic typography inspiration