# Motion

Motion in an interface has one job: to explain what just changed. Something arrived, something left, something moved from here to there, something was pressed. Motion that does not explain a change is decoration, and decoration that moves is the most tiring kind. This page is the motion system MIAN uses, and the rules for adding your own.

## Five reasons to move something

- Purpose: What happens: How long
- Feedback: The control acknowledges the touch: it darkens, shrinks slightly, or drops onto its shadow.: 100–150 ms
- State change: A switch slides, a tab indicator moves, a checkbox draws its tick.: 150–250 ms
- Arrival and departure: A menu, dialog or toast enters from where it came and leaves the same way, faster.: 200–350 ms in, 150–200 ms out
- Spatial continuity: One screen becomes the next: a cross-fade, or a shared element that travels.: 250–400 ms
- Attention: Something needs the reader: a single pulse, once.: One cycle, then stop

## The motion tokens

- --mn-dur-fast: 120 ms. Feedback on press and hover.
- --mn-dur: 200 ms. State changes.
- --mn-dur-slow: 360 ms. Layout changes, large surfaces.
- --mn-ease-out: cubic-bezier(.16, 1, .3, 1). Anything arriving: fast start, long gentle stop.
- --mn-ease-in-out: cubic-bezier(.65, 0, .35, 1). Anything moving from one place to another on screen.
- --mn-ease-spring: a linear() spring. A soft overshoot, for playful noodles only.
- --mn-enter: per noodle. Each noodle’s own entrance. Use it through the mn-enter class.

```
.my-panel {
  transition: opacity var(--mn-dur) var(--mn-ease-out),
              transform var(--mn-dur) var(--mn-ease-out);
}
```

## Rules

- Animate transform and opacity. Animating size, position or shadows makes the page stutter.
- Things leave faster than they arrive.
- Small things move fast, large things move slower, and nothing takes longer than 400 ms.
- Ease out for arrivals, ease in for departures, ease in-out for travel. Linear is for spinners and progress only.
- One moving thing at a time. Stagger a list by 30 to 50 ms per item, for at most eight items.
- Never animate on scroll to make content appear. The reader came for the content; hiding it until they scroll is the best-known mark of a generated page.
- Never loop an animation near text, and never animate while someone is typing.
- Honour prefers-reduced-motion: every MIAN duration becomes zero, and nothing depends on an animation finishing.
- Bounce and overshoot belong to playful products. In a serious one they look dated.

## What MIAN gives you

- Every noodle defines its own entrance (--mn-enter) and durations. Menus, dialogs, toasts and popovers already use them.
- mn-enter and mn-stagger apply the noodle’s entrance to anything you add.
- mn-press and mn-lift give press and hover feedback.
- Mian.transition(fn) wraps a DOM change in a view transition, so it cross-fades; changing noodle or mode already does this.
- data-mn-count counts a number up once, when it is first seen.

[See the motion utilities](https://mian.ro/components/motion)

## Try it

Change the noodle with the picker and press the button: the list enters in that noodle’s own way. On this site, moving between pages and switching a preview’s noodle both cross-fade through a view transition.

- Invoice sent
- Reminder scheduled
- Payment received
- Receipt emailed

Play again

Source: https://mian.ro/docs/motion
