A single element animating is a solved problem: pick a duration, pick a curve, done.
Several elements animating together is where interface motion actually gets hard, and where most of it goes wrong. Not because the individual animations are bad, but because nobody decided what the user was supposed to look at.
The eye tracks one thing
This is the constraint everything else follows from. Human attention does not divide across simultaneous motion. It picks one and loses the rest. Animate six things at once and you have not communicated six changes; you have communicated a disturbance.
So the first question in any sequence is not “how should these move” but “which one of these is the point?”
Usually exactly one element is doing the communicating. A panel opens, and the panel is the point; its contents, the backdrop dimming, and the icon rotating are all support. Get that hierarchy explicit and the rest of the choreography follows almost mechanically.
Three roles
It helps to assign every element in a sequence one of three roles.
Lead: the one thing carrying the meaning. Gets the most movement, the clearest timing, and starts first. There is exactly one.
Support: reinforces the lead without competing. Smaller movements, shorter distances, offset slightly behind. A chevron flipping, a backdrop dimming, contents fading in behind their container.
Static: does not move. This is a real choice and an underused one. Elements that hold still give the moving ones something to be measured against; if everything moves, nothing reads as having moved.
The most common failure is having three leads. The fix is not better timing. It is demoting two of them.
Offsets, not simultaneity
Once roles are assigned, the support elements should lag the lead slightly. Not much: 30–80ms is usually enough to read as following rather than accompanying.
This is follow-through. In physical motion, loosely attached parts do not stop at the same instant as the thing carrying them. A panel whose contents arrive locked to its frame reads as a printed image sliding. The same panel with its contents 50ms behind reads as a container with things in it.
.panel { transition: transform 250ms var(--ease-out); }
.panel > .content {
transition: opacity 150ms var(--ease-out) 100ms; /* 100ms delay */
}
The container leads, the contents catch up and finish together. Note the contents also take less time, because a support animation that outlasts its lead inverts the hierarchy.
Enter and exit are not mirror images
The instinct is to reverse the sequence on the way out. It is wrong for the same reason symmetric durations are wrong.
On entry, order matters because the user is parsing something new: container first, then contents, so there is somewhere for the contents to be.
On exit, the user has already decided. Sequencing the departure means waiting through a performance for something dismissed. Collapse the exit. Everything leaves together, faster.
The one ordering that does help on exit: fade contents out slightly before the container shrinks. Content still visible while its container collapses produces a crushed, folding look. A 50ms head start avoids it.
Total time is the budget
The arithmetic that catches people out, same as with staggered lists:
Total = longest chain of (delay + duration), not the longest single animation.
A 250ms panel with contents delayed 100ms and running 150ms is a 250ms sequence: they land together. Add a third step delayed 250ms and running 200ms and it is now 450ms, which is a noticeably different interaction.
Keep the whole sequence within the band the lead would have occupied alone. If choreography pushes a 250ms panel to 500ms, the choreography is too elaborate. The duration is not too short.
Directional consistency
Elements should enter from where they conceptually live and leave the same way. A menu triggered by a button in the top-right should emerge from the top-right, and collapse back into it.
This is solid drawing applied to sequences: the user is building a spatial model of where things are when off-screen, and contradicting it is disorienting in a way people feel without being able to name. A panel that slides in from the right and exits to the left has told the user two different stories about where it lives.
Do not animate what did not change
In a sequence it is tempting to animate everything on screen for cohesion. Resist it. Elements that did not change should not move. Motion is a signal that something is different, and moving unchanged things is a false signal.
This is also where performance and clarity align. Fewer animated elements means fewer composited layers and less to track. The restraint is free.
A worked example
Opening a modal:
| Element | Role | Motion | Timing |
|---|---|---|---|
| Backdrop | support | opacity 0 → 1 | 200ms, starts at 0 |
| Dialog | lead | opacity + translateY 12px → 0 | 250ms ease-out, starts at 0 |
| Dialog contents | support | opacity 0 → 1 | 150ms, starts at 100ms |
| Everything else | static | none | none |
Total: 250ms. One lead, two supports, no competition. The backdrop is slightly faster so the dialog lands last and holds the eye.
On close: backdrop and dialog both out over 175ms, contents fading 50ms ahead. No stagger, no reversal, done.
The test
Watch the sequence and ask what you looked at. If the answer is “I am not sure” or “everything,” there is no lead and the choreography is decoration.
Then watch it thirty times. Sequences degrade faster than single animations under repetition, because each additional step is another thing to sit through. Most choreography that feels rich on the first viewing wants to be about half as elaborate by the tenth.