Motion
Motion that explains something: feedback, orientation, continuity and the occasional earned moment. Nothing here moves until you ask it to, and the switch below turns all of it down to short fades.
Reduce motion for this site, remembered on this device. Your system setting: checking.
Timing presets
Durations in milliseconds and easing curves from @brandcloud/motion. Press a track, or Play every dot, to move the dots with each token. Under reduced motion every distance is zero, so the dots stay put: that is the point.
CSS
@import "@brandcloud/motion/motion.css";
.panel { transition: transform var(--brand-motion-duration-normal) var(--brand-motion-ease-enter); }duration.instant 80ms
duration.fast 140ms
duration.normal 220ms
duration.slow 320ms
duration.slower 480ms
duration.count is 900ms and moves digits, not layout, so it has its own demo under React presets.
easing.standard0.2, 0, 0, 1easing.enter0.22, 1, 0.36, 1easing.exit0.4, 0, 1, 1easing.move0.65, 0, 0.35, 1easing.linear0, 0, 1, 1Springs
Physical stiffness, damping and mass, so the web and React Native run the same physics. CSS gets each spring as a linear() curve and a duration.
spring.press700 / 32 / 1, settles in394msspring.snappy500 / 40 / 1, settles in289msspring.gentle260 / 30 / 1, settles in441msspring.bouncy380 / 18 / 1, settles in660ms| Group | Values |
|---|---|
| distance (px) | nudge 1, lift 4, reveal 12, dialog 8 |
| scale | press 0.95, pressLarge 0.98, dialog 0.98 |
| stagger | tight 30, normal 50, maxItems 6 |
| budget | maxUiDuration 500, maxStaggerTotal 300, maxConcurrent 3 |
React presets
Spread a preset on a Motion element. Wrap the app in BrandMotionConfig so the OS setting and this page's switch both apply.
TSX
import { LazyMotion, domAnimation, m, AnimatePresence } from "motion/react";
import { BrandMotionConfig, depthButton, dialog } from "@brandcloud/motion/react";
<BrandMotionConfig>
<LazyMotion features={domAnimation}>
<m.button {...depthButton}>Book a visit</m.button>
<AnimatePresence>{open && <m.div variants={dialog} initial="hidden" animate="visible" exit="exit" />}</AnimatePresence>
</LazyMotion>
</BrandMotionConfig>Reduced motion is off for these demos.
press
Down fast, back on the press spring with a small overshoot.
depthButton
1px lift and 4% brighter on hover, press to 0.95.
tierTile
An offer tile lifts 4px on hover or focus, with a light press.
dialog and overlay
The scrim fades while the dialog settles in.
drawer
Slides from the inline end.
sheet
Rises from the bottom, for phone menus and pickers.
list and listItem
Items arrive after a user action, with the stagger capped at 300ms in total.
reveal
One reveal on first view. Use it for one or two moments a page, never every section.
useCountUp
One hero figure at most. Prices never count up.
0
transitions
Named transitions from the tokens, for your own components.
instant80msfast140msnormal220msslow320msslower480mspressspring, stiffness 700snappyspring, stiffness 500gentlespring, stiffness 260
CSS utilities
For Astro and static pages: classes in the brand-motion layer, so your own rules win. Only transform, opacity and filter animate.
.m-press and .m-press-lg
.m-depth
.m-focus
The ring settles in from further out.
dialog.m-dialog
dialog.m-drawer
.m-popover[popover]
.m-spinner
A slow pulse under reduced motion.
.m-enter
[data-reveal] with reveal()
One section per page at most. The reveal script only hides what is below the fold, so nothing already on screen fades out. This page uses it on the box at the bottom of the drivers section.
.m-reveal-scroll
Tied to scroll position with no script. Browsers without scroll-driven animation just show it.
Character and surface presets
From @brandcloud/motion/character.css: weight for things that move, such as a guide, a badge or a card. Use a class (m-settle) or setdata-motion="settle" from script. All of them stop under reduced motion.
One-shot presets
Surface presets on the guide
m-phrase
Hello.
This section explains the prices.
Ask me anything.
m-splash-art, m-splash-rise, m-splash-fade
Welcome back
Your saved brand is ready.
m-card-enter
m-ripple
m-typing (loop)
m-progress (loop)
m-squash
What each preset is for
settle: A landing squash after a glide or a drop.pop-in: Appearing at a new place: a small pop with one squash.hop: A short hop on the spot.celebrate: Anticipation, hop and landing. Once per earned moment.settle-in: First arrival on the page: drops in and settles.hop-out: Leaving one place to reappear at another.stretch: Held while gliding: a slight stretch along the move.hold: Squashed and still while the page scrolls fast.breathe: Idle: a very slow breath. Loops.float: Idle: drifts up and down. Loops.blink: Blinks four times, then stops.nod: A small nod. Loops.wave: Waves twice.phrase: Phrases arrive in order, each with --i.splash-art: A splash or panel opening: the art rises first.splash-rise: Then the text rises, with --i for order.splash-fade: Then the rest fades in.card-enter: A card arriving in a list or conversation.ripple: A touch ripple from the press point (--x, --y).typing: Typing dots, each with --i. Tie it to real progress.progress: The moving part of an indeterminate progress bar. Loops.squash: Squash on press, spring back on release. Works under reduced motion too.
Spring drivers
From @brandcloud/motion/character. Each runs one animation frame loop only while something moves, and jumps under reduced motion.
TS
import { flyTo, hopTo, springFollower, turntable, playPreset } from "@brandcloud/motion/character";flyTo: along an arc, then settles
Basket
Click an item to send it to the basket.
springFollower: a guide that keeps level
Click a row: the guide glides there, stretches on the way and settles.
hopTo: out, moved, popped in
turntable: drag, release, turn
Drag the dial, or use the arrow keys. It springs to the nearest quarter turn.
reveal(). With reduced motion it was simply there.The rules that keep motion honest
- Every animation has a job: feedback, orientation, continuity or an earned moment of delight.
- Interface movement stays under 500ms. Exits are shorter than entrances.
- Nothing loops unless it shows progress, and loops stop off screen.
- Under reduced motion there is no travel, scale, overshoot or parallax. Short fades stay so things still visibly appear.
- Content is never hidden waiting for an animation.