animation-motionlisted
Install: claude install-skill soumit-kaz/lazysitter
# Animation and motion
## Motion must do a job
Good motion explains a change: where something came from, that a list reordered rather than replaced, that an action was received. Motion added for polish costs frame budget and user attention, and it is the first thing that feels broken on a slow device.
State the job before implementing: *"the drawer slides from the right so the user knows where it will return to."* If there is no such sentence, consider not animating.
## Animate the cheap properties
Only two categories are handled by the compositor without recalculating layout or repainting:
- **`transform`** — `translate`, `scale`, `rotate`
- **`opacity`**
Everything else is expensive. Animating `width`, `height`, `top`, `left`, `margin` or `padding` triggers **layout on every frame** for the element and often its siblings — this is the single most common cause of janky UI animation.
| instead of | animate |
|---|---|
| `left` / `top` | `transform: translate()` |
| `width` / `height` | `transform: scale()` (with care for text) |
| `margin` | `transform: translate()` |
| `display: none` ↔ `block` | `opacity` + `visibility`, or `@starting-style` |
For size changes where `scale` distorts content, the FLIP technique (measure First and Last positions, apply an Inverted transform, then Play it out) gives a layout-accurate animation using only transforms.
`will-change` promotes an element to its own layer — use it sparingly and remove it after. Applied broadly it costs memo