The document that stops the fourteen questions
A designer sends a video of the intended animation. A developer builds it. It is wrong in six ways, none of which were discussed, all of which were invisible in the video. Three rounds of review later, it ships, subtly different from the design and impossible to reproduce elsewhere.
The fix is a written specification. It is not bureaucracy; it is the shortest route to the thing being right, and it takes about fifteen minutes to write.
What a developer cannot get from a video
A video shows one playthrough of one happy path. It does not show:
- What triggers it. Page load? Element entering the viewport? A click? A successful response? “On load” and “on scroll into view” look identical in a recording and are different code.
- What interrupts it. The user clicks again while it is running. The user navigates away. The data arrives early.
- The exit. Almost every recorded animation shows the entrance and stops. What happens when the element leaves is a separate decision and is usually forgotten until QA.
- Whether it loops, how many times, and whether it rests on a final pose.
- What happens at other sizes. The same animation on a 360px phone and a 1440px desktop is rarely the same numbers.
- The reduced-motion behaviour.
- Which properties are moving. Is that growth a scale or a width? They look similar and behave differently: a scale distorts the text inside it, a width re-runs layout.
The template
One of these per animation, in whatever tool you already use. Plain text is fine.
NAME sheet-enter
TRIGGER user taps a list row
INTERRUPT tapping another row: cancel, reverse at current position
ELEMENT .sheet
translateY 100% -> 0 360ms ease-enter
opacity 0 -> 1 160ms linear
ELEMENT .scrim
opacity 0 -> 0.4 200ms linear (starts at 0ms)
ELEMENT .sheet-content children
translateY 12px -> 0 240ms ease-enter stagger 30ms, max 6
(starts at 120ms)
EXIT reverse of enter, 260ms, ease-exit; scrim fades over 200ms
LOOP none
RESPONSIVE below 600px the sheet is full-height; above, 640px max-width,
translateY distance is the sheet height either way
REDUCED MOTION no translate; opacity only, 120ms; no stagger
ASSETS noneAnybody can build that, including you in a year. Note what it makes explicit that a video hides: the scrim and the sheet start together but the content waits 120ms, the exit is faster than the entrance, and the stagger is capped.
Naming, so the file is findable
For a delivered file (a Lottie, a video, a sprite sheet) the name is part of the specification.
checkout-success-loop-512.json tells a developer where it goes, what it does, whether it repeats, and its authored size. Comp 1 (1).json tells them nothing, and it is what they will receive unless the convention is written down.
Inside the file, name the layers too. A developer debugging a Lottie in the DOM inspector sees your layer names. Shape Layer 14 is a cost you are passing on.
The handover checklist
Before sending anything:
- Does it play correctly on a real device on each target platform, not in the authoring tool?
- Is the file size stated, and is it what you expected? A 900KB Lottie means an image got embedded.
- Is there a static fallback (a poster frame, an SVG, a first-frame PNG) for reduced motion and for load failure?
- Are the frame ranges or state names listed, if the developer needs to play parts of it?
- Does the specification say what happens on interrupt and on exit?
- Has somebody who did not make it read the specification and built a mental model that matches yours?
That last one catches more than the other five together.
Review it as a moving thing
A motion specification cannot be signed off as a document. Build a page (a plain HTML file is enough) that renders every animation in the system, with controls to replay, to slow to a quarter speed, and to toggle reduced motion. Open it on the oldest phone in the office.
Quarter speed is where the problems are visible. At full speed, everything looks fine, because the eye forgives a great deal in 250ms. At 25 per cent, you can see the overshoot that is one frame too long, the element that starts three frames late, the opacity that finishes before the movement does.
Chrome DevTools has an animation speed control built in, free, under the Animations panel. Use it before the review, not after.
The free path
None of this needs tooling. A markdown file in the repository next to the component beats a specification in a design tool that developers do not have a seat for. If you want it rendered, a static site generator or a plain HTML page is enough. Storybook is free and is the usual home for the live version; a single motion.html works just as well for a small team.
The limitation
A specification describes intent, and motion is judged by feel. Two implementations matching the same numbers can feel different if one of them drops frames, or starts a frame later because of how it is triggered, or runs on a device with a 120Hz display where the curve resolves differently.
So the document is necessary and not sufficient. It removes the category of disagreement that comes from ambiguity, which is most of them, and leaves the category that comes from taste, which is the one worth arguing about.
Every lesson here is open. Your progress is recorded once you pass the Video with AI exam.
Check your understanding
Why is reviewing an animation at 25 per cent speed more useful than reviewing it at full speed?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Deepa, your AI tutor
