Shots in this scene
Storyboarding and Motion Specs
In one line
Before code, draw the motion: a storyboard of key frames, and a spec table with trigger, element, property, from, to, duration, easing, delay and a reduced-motion answer. A spec turns "make it feel nice" into numbers a developer can build and a tester can check.
Think of it like this
A film is storyboarded before it is shot, because changing a drawing is cheap and changing a filmed scene is not. Motion is the same: a sheet of numbers is cheap to change, a built component is not.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- storyboard
- A set of key frames showing a motion from start to end, drawn before any code.
- key frame
- A frame that fixes a value at a moment, such as opacity 0 at 0 ms and 1 at 240 ms.
- motion spec
- A table that gives every motion's trigger, target, property, values, timing and reduced-motion version.
- handoff
- Passing a design to the people who build it, with everything they need to build it without guessing.
Step by step
01Draw the frames
Sketch the start, the end and one or two moments between. Write the time under each.
02Fill one row per motion
Trigger, element, property, from, to, duration, easing, delay. Use token names for the timing.
03Add the calm column
Write what a person who asked for less motion sees. A row with an empty cell is not finished.
04Add what rows cannot say
Interruption, failure, loading, empty, and right-to-left. Put these as notes under the table.
Try it yourself
- 1
Fix the hero row
In the spec example, change the hero row to
property: "transform", from: "translateX(0)", to: "translateX(120px)", ms: 400, easing: "ease", reduced: "fade only". Run: all three lines say ok, and Play now makes a green composite track. - 2
Change the storyboard's easing
In the storyboard example, change the easing to
"linear"and press Run. The opacities become 0.00, 0.17, 0.33, 0.67 and 1.00: even steps. The frames look different because the speed is no longer front-loaded.
Code & diagrams
Read the console, then press Play on each row. The hero row animates `left` (the track is red: layout cost), lasts 1200 ms and has no reduced-motion plan.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Expected console output
toast enters: ok
cart count bump: ok
hero slides in: longer than 500 ms; animates left (costs layout or paint); no reduced-motion planFive paused copies of one toast. Each track on the timeline is paused at its own moment. Pausing and setting `currentTime` is the same trick the timeline uses to scrub.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Expected console output
0 ms: opacity 0.00
40 ms: opacity 0.60
80 ms: opacity 0.87
160 ms: opacity 0.99
240 ms: opacity 1.00Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Leave the reduced-motion cell empty
In the spec example, change the toast row's reduced: "fade only" to reduced: "". Press Run.
Break #2
Write a value the browser silently ignores
Change the toast row's from: "translateY(8px)" to from: "translateY(8)", press Run and press Play on that row.
Myth vs fact
Myth
Storyboards and specs are only for big teams.
Fact
A solo developer benefits just as much: the spec is where you decide, so you decide once.
Myth
A spec kills creativity.
Fact
It moves the arguing before the build. Rows are cheap to change, and feel is still tested on real motion.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
A spec table is testable. The exercise helpers'
anim.list()returns the same fields (property, duration, easing, delay), and Phase 18 turns rows into automatic tests. - ▸
Spec the cost too: a row that animates
leftorheightshould say why, because layout cost is invisible in a mock-up (Phase 6).
Remember this
- 1
The problem this solves: without a spec, a designer says "make it snappy", the developer guesses, and they go back and forth: "a bit faster?", "a bit softer?". Every motion becomes a one-off. A spec is the handoff: one row per motion, with numbers both sides can read.
- 2
The storyboard. Draw the key frames of a motion: the start, the end and one or two between. Label each with its time. The second example makes one from the real animation: five copies of a toast, each paused at a different moment (0, 40, 80, 160 and 240 ms). It prints opacity 0.00, 0.60, 0.87, 0.99 and 1.00, so most of the change happens in the first 80 ms. That is what ease-out looks like.
- 3
The spec table. The columns are trigger, element, property, from, to, duration, easing and delay, plus one for reduced motion. The first example holds three rows as data, shows them as a table, plays each, and checks them: over 500 ms, a property that costs layout or paint, or a missing reduced-motion plan. The hero row fails all three. (Layout and paint are per-frame steps: Topic 1.4.)
- 4
What a spec leaves out. Rows describe the happy path. Add notes for what happens when the user interrupts (a second click mid-motion), when something fails (an animation file that does not load), for loading and empty states, and for right-to-left pages. Without them the developer decides alone, and decides differently each time.
- 5
Handoff and tokens. Keep the spec in the repo (
docs/motion-spec.md), next to the code, so it changes with it. Durations and easings in the spec should be names (fast,ease-out) that match tokens in the code (the build topic). A tester can then check the page against the spec: the timeline's tracks show the same numbers. - 6
A limit of validation. The checker in the example catches rows that break the rules, not rows that are wrong. A
fromoftranslateY(8)(no unit) is silently ignored by the browser: Play creates a track and nothing moves, and the checker still says ok. Always play a row after writing it.
Explain it without notes
What columns belong in a motion spec, and why a reduced-motion column?
What does a spec table not say, and how do you cover it?
Practice
Write a spec row for the Reserve button's confirmation, and a four-frame storyboard in words.
Add a fourth row to the spec example for the cart drawer and make the checker report it ok.
Done when you can
You can storyboard a motion with key frames and times
You can write a spec row with every column, including reduced motion
You know what a spec leaves out and how to cover it