Motion
A small motion system: three durations, three curves, the noodle’s own entrance for anything you add, staggered lists, press and lift feedback, drawn lines, counted numbers and cross-faded changes. All of it stops under reduced motion.
Entrance and stagger
Press the button: the list is re-inserted and enters in this noodle’s own style.
- Invoice sent
- Reminder scheduled
- Payment received
- Receipt emailed
<div class="mn-stack" style="width:min(100%,22rem)">
<ul class="mn-list mn-stagger" id="motion-list"><li>Invoice sent</li><li>Reminder scheduled</li><li>Payment received</li><li>Receipt emailed</li></ul>
<button class="mn-btn mn-btn-outline mn-press" type="button" onclick="const l=document.getElementById('motion-list');const c=l.cloneNode(true);l.replaceWith(c)">Play again</button>
</div>Press, lift and count
<div class="mn-row" style="--mn-gap:1rem">
<a class="mn-card mn-lift" href="#" style="display:block;padding:1rem 1.25rem;text-decoration:none;color:inherit"><span class="mn-muted" style="font-size:.8125rem">Orders today</span><br><strong style="font-size:1.5rem" data-mn-count>1,284</strong></a>
<button class="mn-btn mn-press" type="button">Press me</button>
</div>Installation
Everything ships in one stylesheet and one small script. There is nothing to import per component.
<link rel="stylesheet" href="https://mian.ro/dist/mian.css">
<script src="https://mian.ro/dist/mian.js" defer></script>Prefer to own the files? /r/motion.json is a registry item with this component's CSS and example markup, ready to copy into your project with any tool that reads the open registry-item format.
Class reference
| Class / attribute | Description |
|---|---|
| --mn-dur-fast · --mn-dur · --mn-dur-slow | 120, 200 and 360 ms: feedback, state change, layout change. |
| --mn-ease-out · --mn-ease-in-out · --mn-ease-spring | Arriving, moving across the screen, and a soft overshoot for playful noodles. |
| mn-enter | Plays the current noodle’s entrance once, when the element is added. |
| mn-stagger | On a container: its first eight children enter 45 ms apart (--mn-stagger-step). |
| mn-press | Shrinks to 97% while pressed. |
| mn-lift | Rises 2px with a shadow on hover, for whole-card links. |
| mn-draw | On an SVG path with pathLength="1": draws the line in. |
| data-mn-count | Counts up to the element’s own number once, when first seen. |
| Mian.transition(fn) | Runs a DOM change inside a view transition, so it cross-fades. Mian.setNoodle and Mian.setMode use it. |
Accessibility
- Everything here is disabled by prefers-reduced-motion: reduce; nothing depends on an animation finishing.
- Animate to explain a change (something arrived, moved, was pressed), not to decorate. Do not fade sections in as the reader scrolls.
- Keep motion under 400 ms and never loop it near text.
- Counted numbers keep their final value in the DOM, so assistive technology never reads a partial count.