Skip to content

Motion ​

Motion tokens for panels that slide in and out, and for the backdrop behind them. They live in public/assets/styles/motion.css and load with main.css.

All panels use one curve pair. The duration follows how far the panel travels, so a small menu and a wide slide-in feel equally quick. Exit is shorter than enter.

Tokens ​

TokenValueUse
--motion-ease-entercubic-bezier(0.2, 0, 0, 1)Panel enters: starts fast, settles
--motion-ease-exitcubic-bezier(0.4, 0, 1, 1)Panel leaves: speeds up as it goes
--motion-ease-fadelinearBackdrop fade
--motion-duration-sm-enter / -exit180ms / 140msTravel up to 420px: menus, narrow panels
--motion-duration-md-enter / -exit220ms / 160msTravel 421 to 640px: side panels
--motion-duration-lg-enter / -exit260ms / 180msTravel above 640px: slide-ins
--motion-duration-backdrop-enter / -exit120ms / 100msBackdrop: starts with the panel, finishes sooner

When the user asks for reduced motion (prefers-reduced-motion: reduce), every duration is 0ms.

Usage ​

Animate transform, not width, left or margin. Set the enter timing on the open state and the exit timing on the closed state, so each direction uses its own pair.

css
.side-panel {
  transform: translateX(-100%);
  transition: transform var(--motion-duration-md-exit) var(--motion-ease-exit);
}

.side-panel.is-open {
  transform: translateX(0);
  transition: transform var(--motion-duration-md-enter) var(--motion-ease-enter);
}

.backdrop {
  opacity: 0;
  transition: opacity var(--motion-duration-backdrop-exit) var(--motion-ease-fade);
}

.backdrop.is-open {
  opacity: 1;
  transition: opacity var(--motion-duration-backdrop-enter) var(--motion-ease-fade);
}
.side-panel {
  transform: translateX(-100%);
  transition: transform var(--motion-duration-md-exit) var(--motion-ease-exit);
}

.side-panel.is-open {
  transform: translateX(0);
  transition: transform var(--motion-duration-md-enter) var(--motion-ease-enter);
}

.backdrop {
  opacity: 0;
  transition: opacity var(--motion-duration-backdrop-exit) var(--motion-ease-fade);
}

.backdrop.is-open {
  opacity: 1;
  transition: opacity var(--motion-duration-backdrop-enter) var(--motion-ease-fade);
}

A page that moves to make room for a panel uses the same duration and curve as the panel, so both arrive together.