Skip to content
Site volume
Colourway

Motion

Transitions

How a page changes: the wipe over a soft navigation, the head that lands, plates arriving, and the overlays, toasts and disclosures between.

  • Experimental
On this page

A transition answers a change of state, and the state comes first: the new page is in the DOM in the next frame, and the motion plays over it. Nothing waits for an animation, nothing that takes taps ever covers the page, and a key pressed during an arrival finishes the arrival before it acts.

How a route changes on this site#

Links here are soft navigations: the App Router renders the next page at once and swaps the page's DOM, so the header, the sidebar, the cursor and the sound stay put. Then:

  1. At Press and Rave, the page wipe sweeps three bands across the view while the new page renders under it. It takes no pointer events, so a tap during the sweep lands on the new page.
  2. The head lands: the title rises and fades in, its second ink registers, then the eyebrow, the lede and the chips rise after it.
  3. The plates arrive (example frames, tables, code, callouts) as panels, the ones in view at once with the stagger, the rest as you scroll. Running text never slides; it fades in under the head.
  4. Focus moves to the new title, so a screen reader and a keyboard start at the top of the new page.

At Quiet the page simply fades in (160 ms); under reduced motion it crossfades in 140 ms. There are no View Transitions for routes anywhere in the system: they lost taps and started late in Chromium and WebKit.

Page wipeMoment 16

A plain click on a link to another page. The new page renders under it; it takes no taps.

The bands, caught mid-sweep
Page wipe: controls

Play sweeps the real wipe across this page at the volume picked here. Studio has none.

Quiet
None
Studio
None: the page arrives (title, panels)
Press
Three bands in the field's inks with halftone fringes sweep across once, 410 ms (wipe in, wipe-exit out)
Rave
480 ms
Reduced motion
None. The docs crossfade the new page in 140 ms instead.
Sound
flip
Tokens
--mk-dur-wipe --mk-dur-reduced --mk-ease-wipe --mk-ease-wipe-exit
Keyframes
mk-page-wipe
Who plays it
PageWipe · @maxgrits/overprint-react/motion · Page wipe

Use it Over client-side route changes on a loud site or section.

Not when View Transitions for routes (they lose taps); a wipe that waits for the page or covers a form.

Title arrivalMoment 2

A soft navigation (the runtime sets html[data-mk-nav]). The hard load's title never fades: it holds the LCP.

Case study

Fernlight

A booking site for a plant shop in Leith, live in six weeks.

Title arrival: controls

As after a client navigation; on a hard load the title is simply there.

Quiet
160 ms fade
Studio
Rises 0.12 em and fades in, 360 ms on title
Press
440 ms, plus a width stretch-in on a display title of three words or fewer
Rave
520 ms, plus the stretch-in
Reduced motion
None: the title is there.
Sound
None
Tokens
--mk-dur-arrival --mk-ease-title
Keyframes
mk-title-in mk-stretch-in
Who plays it
MotionRuntime and the kit's mk-title-in · @maxgrits/overprint-react/motion · PageHero, SectionHead

Use it On the page's one title after a client navigation.

Not when On a hard load, on body text, or on more than one heading per page.

Second-ink registerMoment 3

A display line with the second ink enters the view (on a hard load too).

Websites that win

Second-ink register: controls

Press shows the art's cyan and yellow plates collapsing too.

Quiet
Off
Studio
The second ink lands three times its rest offset away and snaps to rest in 520 ms on register, then stays
Press and Rave
Same, and the cyan and yellow plates collapse with it
Reduced motion
At rest at once.
Sound
None
Tokens
--mk-dur-register --mk-ease-register
Keyframes
mk-snap mk-misreg-in
Who plays it
Misregistration · @maxgrits/overprint-react/print · Misregistration and the second ink, PageHero

Use it On display type of 2 rem and up: page titles, hero lines, splash titles.

Not when On body text, labels, names or numerals in rows: at small sizes the offset reads as blur.

Panel entranceMoment 4

A [data-mk-reveal="panel"] plate enters the view, once (the pre-paint script marks it, before React).

Fernlight

A booking site for a plant shop, live in six weeks.

Pebblepath

Trail maps that work offline, for the Saturday walkers.

Sam Okafor Joinery

Quotes in a day: one form, one price, one call back.

Panel entrance: controls
Quiet
None
Studio
Rises 24 px and fades in, settles 2 px past rest, 300 ms on out, 40 ms apart
Press
Also scales 0.97 to 1.01 and turns from −0.8°, 360 ms, 48 ms apart
Rave
From 40 px, −2° and 0.94 with an overshoot, 420 ms on slap, 55 ms apart
Reduced motion
None: every panel is there.
Sound
None
Tokens
--mk-dur-panel --mk-dur-panel-stagger --mk-ease-out --mk-ease-slap
Keyframes
mk-panel-in-studio mk-panel-in-press mk-panel-in-rave
Who plays it
The reveal runtime · @maxgrits/overprint-react/motion · Section, Card, Plate, LineCard

Use it Plates and cards arriving as they scroll into view; at most eight per batch.

Not when On running text without a plate, on controls, or scrubbed with the scroll.

Press runMoment 1

The first visit to a boot path (the home). Any key, click or touch skips it.

Press run: controls

Play runs the real press run over this page. Any key or click skips it.

Quiet
None
Studio to Rave
800 ms: the mark's four plates print 120 ms apart, each landing 6 px out of register and snapping in, then the paper wipes off in 300 ms
Reduced motion
None: the page shows at once.
Sound
None (a first visit has had no gesture to unlock audio)
Tokens
--mk-dur-press-run --mk-dur-reduced --mk-ease-register --mk-ease-snap --mk-ease-squeegee
Keyframes
mk-press-run-plate mk-press-run-wipe mk-press-run-failsafe
Who plays it
PressRun · @maxgrits/overprint-react/motion · Press run

Use it Once, on the first visit to the front door of a site.

Not when On every page or every visit, behind a form, or anywhere a reader came to read fast.

Re-ink and themeMoment 17

The visitor turns the volume dial, picks a colourway or swaps the paper.

Site volume
Re-ink and theme: controls

These are the site's own controls: the whole page changes, not just this frame.

Quiet
400 ms crossfade
Studio to Rave
700 ms colourway, 400 ms paper; the field and the 3D re-ink with it
Reduced motion
A 140 ms crossfade.
Sound
None
Tokens
--mk-dur-reink --mk-dur-theme --mk-ease-in-out
Who plays it
VolumeDial, ThemeToggle and the tokens · @maxgrits/overprint-react · ThemeToggle, VolumeDial, VisitorControls

Use it When the reader changes the look themselves.

Not when On a timer or on scroll: the look changes only when someone asks.

Overlays, toasts and disclosures#

The reading layer moves the same at every volume: these never get louder with the dial.

Toast

Your code raises a toast; it leaves on its own after its life, or when dismissed.

Toast: controls

The toast drops in at the foot of your view, drains for 5.2 s and leaves.

Every volume
Drops in 380 ms, drains over 5.2 s, leaves in 260 ms
Reduced motion
Fades in and out in 140 ms; the drain still counts down.
Sound
None
Tokens
--mk-dur-toast-in --mk-dur-toast-out --mk-dur-toast-life --mk-dur-reduced --mk-ease-out
Keyframes
mk-toast-in mk-toast-drain mk-toast-fade
Who plays it
Toast · @maxgrits/overprint-react/toast · Toast

Use it A short confirmation with an undo.

Not when Errors that need a decision, or anything the reader must read twice.

Disclosure

The reader opens or closes it.

Do I own the code?

Yes, from day one: the repository is yours.

How long does a site take?

Two to four weeks for most small businesses.
Disclosure: controls
Every volume
Unfolds in 180 ms, the chevron turns
Reduced motion
Opens at once.
Sound
None
Tokens
--mk-dur-disclosure --mk-ease-out
Who plays it
Disclosure and Faq · @maxgrits/overprint-react/disclosure · Disclosure

Use it Answers and details the reader asks for.

Not when Hiding the one thing every reader needs.

Dialog

The reader opens it; Escape or Close closes it.

Open one on the Dialog page

Every volume
In 240 ms, out 160 ms
Reduced motion
Fades in 140 ms.
Sound
None
Tokens
--mk-dur-overlay-in --mk-dur-overlay-out --mk-dur-reduced --mk-ease-out
Who plays it
Dialog · @maxgrits/overprint-react/dialog · Dialog

Use it A decision that needs the reader before anything else.

Not when Messages that could sit on the page.

Drawer

The reader opens it.

Open one on the Drawer page

Every volume
Slides in 280 ms, out 200 ms
Reduced motion
Fades in 140 ms.
Sound
None
Tokens
--mk-dur-drawer-in --mk-dur-drawer-out --mk-dur-reduced --mk-ease-out
Who plays it
Drawer · @maxgrits/overprint-react/drawer · Drawer, NavSheet

Use it A side task: a quote form, the phone menu.

Not when Content that belongs on its own page.

The reader opens a menu or a nav panel.

Open one on the Menu page

Every volume
Menus in 140 ms; the nav panel unfolds in 180 ms
Reduced motion
The panel fades in 140 ms.
Sound
None
Tokens
--mk-dur-menu --mk-dur-disclosure --mk-dur-reduced --mk-ease-out
Keyframes
mk-navbar-panel-in mk-navbar-panel-fade
Who plays it
Menu and Navbar · @maxgrits/overprint-react · Menu, Navbar

Use it Every menu and nav panel.

Not when Menus that open on hover alone.

Keys and gauges#

Hover and pressMoment 20

The pointer rests on a control; a press goes down.

Hover and press: controls

Each key steps through its hover and press (the press check's forced states); then try them.

Quiet
Colour only
Studio to Rave
Colour, a lift of 2 px or less; a key sinks 2 px into its offset in 120 ms
Reduced motion
Colour only.
Sound
None
Tokens
--mk-dur-hover --mk-dur-press --mk-dur-key-sink --mk-ease-out --mk-ease-pop
Who plays it
Button and every control · @maxgrits/overprint-react · Button, IconButton, Card, Link

Use it Every control says it can be pressed, and every press is felt.

Not when Hover that moves words, grows a box or reflows the layout.

Pending key

A key's action is under way (loading).

Pending key: controls
Every volume
The label stays; a 2 px bar in its ink draws under it every 1.2 s while it waits
Reduced motion
No bar; the key stays busy (aria-busy) and its label says what is happening.
Sound
None
Tokens
--mk-dur-reduced --mk-ease-out
Keyframes
mk-button-pending
Who plays it
Button · @maxgrits/overprint-react/button · Button

Use it While a form sends or a payment confirms.

Not when As decoration: it runs only while something is really pending.

Gauge

The dial enters the view: its arc draws to the score.

Gauge: controls
Every volume
Draws in 900 ms
Reduced motion
Drawn at once.
Sound
None
Tokens
--mk-dur-gauge --mk-ease-out
Keyframes
mk-score-dial-draw
Who plays it
ScoreDial · @maxgrits/overprint-react/score-dial · ScoreDial

Use it One score that was earned (a Lighthouse result).

Not when Dials for every number on a page.

Loader

Something is loading; the label stays still beside the glyphs.

Sending
Loader: controls
Every volume
Three ink glyphs hop in turn, 900 ms a cycle, 150 ms apart, five cycles at most, then still
Reduced motion
Static, with its words.
Sound
None
Tokens
None--mk-ease-pop
Keyframes
mk-loader-hop
Who plays it
Loader · @maxgrits/overprint-react/loader · Loader

Use it A wait of more than about a second, with a label.

Not when Waits under a second (show the result), or a loader with no words.