Case Study · Episode 06 · Animated SVG

Drawn to move: a pastel menagerie, hand-animated in SVG

Poppet is a cast of fourteen mascots — a sprout, a fox, a whale, a snail, a moon — each one a single inline SVG brought to life with nothing but CSS keyframes. No Lottie, no After Effects, no framework. This case study is the field guide: the handful of habits that make an SVG character feel alive, built and recoloured live with Claude Code, and playable right here on the page.

CollectionPoppet · a pastel menagerie
StackInline SVG + CSS keyframes · zero libraries
Cast14 characters across 3 scenes
InteractionEvery mascot cheers when tapped
The Interactive

Pick a scene — it's alive

These are the real SVGs running live, not recordings. Every character idles on its own — bobbing, blinking, swaying — and springs into a cheer the moment you tap it, complete with a little burst of confetti.

tap — the sun, the sprout, the fox, the bunny, the flower, the bee or the snail Open fullscreen ↗
Overview

Not one line of animation library. On purpose.

Every wiggle, blink and bounce is a CSS @keyframes rule acting on a plain SVG shape. That constraint is the lesson: when the whole toolkit is "shapes plus keyframes," the technique is transferable to any character you'll ever draw — and the file stays tiny, portable and future-proof.

14Mascots, one visual language
0Animation libraries or plugins
CSSKeyframes do all the motion
100%Interactive — every mascot reacts
The Cast

Fourteen mascots, fourteen little lessons

Each character was chosen to show off one animation habit. Together they cover the whole vocabulary — squash and stretch, secondary motion, staggered timing, anticipation, easing. Every card opens the scene it lives in.

Sprout
the little sprite · Meadow
Squash & stretch

Bobs on a soft scaleY so it feels weighted; leaps on a bouncy overshoot easing when tapped.

MEET SPROUT ↗
Ziggy
the energetic fox · Meadow
Secondary motion

The body bounces, but the tail wags on its own faster loop — motion that follows the main motion.

MEET ZIGGY ↗
Buzz
the busy bee · Meadow
Fast flutter

Wings beat on a 0.18s loop while the body drifts slowly — two clocks running at once sells "hovering."

MEET BUZZ ↗
Hopper
the bunny · Meadow
Anticipation

Before the jump it dips and squashes down — the tiny wind-up that makes the leap read as effort.

MEET HOPPER ↗
Bloom
the flower · Meadow
Pivot & origin

Sways from the base of its stem, not its centre — a lesson in getting transform-origin right.

MEET BLOOM ↗
Shelly
the snail · Meadow
Easing

Glides on a gentle ease-in-out; the shell spiral breathes on a slower beat. Slow is a choice, too.

MEET SHELLY ↗
Sunny
the sun · Meadow
Radial rotation

Rays spin on a slow linear loop while the face pulses — steady rotation layered over a soft breath.

MEET SUNNY ↗
Luna
the moon · Nightfall
Glow pulse

A halo behind the crescent scales and fades in sync with the drift — light as an animated layer.

MEET LUNA ↗
Twinkle
the star · Nightfall
Scale twinkle

Rocks and swells on a single loop; three mini-stars twinkle on offset delays around it.

MEET TWINKLE ↗
Blush
the shy cat · Nightfall
Staggered blink

Ears twitch and eyes blink on different, rarely-firing loops so the face never feels robotic.

MEET BLUSH ↗
Kitty
the curious cat · Nightfall
Squash hop

Hops with a compress-then-stretch; the tail sways on its own hinge the whole time.

MEET KITTY ↗
Marina
the gentle whale · Lagoon
Buoyant float

Rocks with a paired translate-and-rotate; the spout shimmers and the fin flaps off-beat.

MEET MARINA ↗
Splash
the fish · Lagoon
Tail follow-through

Tail flicks fast against a slow swim; a tap sends it into a full barrel-roll cheer.

MEET SPLASH ↗
Cloudy
the rain cloud · Lagoon
Looping detail

Five raindrops fall forever on staggered delays — a self-contained loop that never needs a trigger.

MEET CLOUDY ↗
The Craft

Eight habits that make an SVG feel alive

None of this is hard — it's a small set of disciplines, applied consistently. Give these to Claude Code as house rules and every new character comes out of the oven already breathing.

01Tokens before shapes

Define the palette as :root variables first, then draw against --mint, --pink, --ink. Restyling the whole cast becomes a token swap, not a redraw — which is exactly how a second, boldly-outlined set got folded into this one.

02SVG draws, CSS moves

Keep every shape in the SVG and every motion in a CSS @keyframes. They never fight, and you can retune the timing of a wave or a blink without touching a single path point.

03Mind the transform-origin

A wagging tail or flapping ear has to pivot where it joins the body. Set transform-origin in the SVG's own coordinate space — get it wrong and the part swings from the corner of the canvas.

04Layer idle over reaction

A slow infinite loop (bob, blink, sway) gives life at rest; a one-shot .cheer class gives a reward on tap. Re-trigger the one-shot with the void el.offsetWidth reflow so it can fire again and again.

05Stagger anything paired

Offset the animation-delay on the second eye, ear or wing by a fraction of a second. Perfect unison reads as mechanical; a few milliseconds of drift reads as alive.

06Blink like you mean it

Keep eyes open for 92–95% of the loop, then shut them in one fast keyframe. A blink you could set a metronome to is worse than no blink at all.

07Cheeks, glints & a shadow

Three cheap tricks sell warmth: a pink cheek that pulses, a white highlight parked in each eye, and a ground-shadow that shrinks as the character rises. Together they cost a dozen lines and do half the work.

08One file, honour reduced-motion

Inline SVG in a single HTML file — no build, drops straight into an <iframe>. Then wrap the loops so one prefers-reduced-motion query can still them. Motion is a garnish, not the meal.

Behind the Scenes

Two styles, one palette

Poppet started as two unrelated sets: a soft pastel squad, and a bold, black-outlined "block crew" in loud saturated colours. Rather than redraw the second group, we treated colour as data — pulling the pastel set's swatches into :root tokens, then asking Claude Code to remap the block crew's fills onto them and drop the heavy outlines for the pastel style's soft belly-shading and thin #4A4458 ink features. Same shapes, same animations — a completely different, unified cast. That's the whole argument for tokens: a coat of paint should never mean a rebuild.

Toolbox

Everything used, and what it did

Inline SVG
Every mascot hand-drawn as paths, ellipses and strokes
NO ASSETS
CSS Keyframes
All motion — idle loops, cheers, blinks, sparkle bursts
BUILT-IN
Claude Code
Drew the cast, recoloured the crew, composed the scenes
AGENT
A dash of JS
Ten lines: add the cheer class, spawn the confetti
VANILLA
Headless Edge
Rendered the scenes to PNG stills for the thumbnail
NO EDITOR
The Source ↗
All three scenes + the fourteen mascots, readable
GITHUB