Motion
The kit animates very little, on purpose: motion in a hypermedia app should explain a state change, not decorate it. What does animate reads from one small scale, so overlays and controls feel like one system.
The scale
Section titled “The scale”Durations and easings are semantic tokens (emitted as --hc-motion-*
custom properties):
| Token | Value | Use for |
|---|---|---|
--hc-motion-duration-fast | 120ms | Hover/press feedback, small state flips (rating stars). |
--hc-motion-duration-base | 200ms | Overlay enter/exit (dialog, drawer, toast), panel reveals, progress bar updates. |
--hc-motion-duration-slow | 320ms | Large surfaces moving a long way (full-height sheets). Rarely needed. |
--hc-motion-easing-standard | ease | Property changes that stay on screen (color, translate-in-place). |
--hc-motion-easing-enter | cubic-bezier(0, 0, 0.2, 1) | Entering elements — start fast, settle gently (decelerate). |
--hc-motion-easing-exit | cubic-bezier(0.4, 0, 1, 1) | Leaving elements — accelerate away (the eye doesn’t follow exits). |
Loaders are not on this scale: the spinner, skeleton shimmer and indeterminate progress keep their own longer cycles — they communicate “still working”, not a state change.
What consumes it
Section titled “What consumes it”- Dialog fades + settles in/out (
--hc-dialog-duration, enter/exit easings,@starting-style+transition-behavior: allow-discrete). - Drawer slides on
--hc-drawer-durationwith the standard easing. - Toast snap-back / fly-out uses
--hc-toast-duration. - Rating and progress transitions reference the scale’s fast/base steps.
Component durations stay overridable per component
(--hc-dialog-duration: 150ms;) — they default to the scale.
Rules of thumb
Section titled “Rules of thumb”- Animate state changes, not attention. An element entering, leaving, or moving may animate; nothing should pulse or bounce to attract clicks.
- One property set per pattern. Overlays fade/settle; panels slide; feedback recolors. Don’t combine three effects on one element.
- Exits faster-feeling than entrances. Use the exit easing — users have already decided to leave; don’t make them watch.
- Respect
prefers-reduced-motion. Every kit transition collapses to0msunder it. Do the same for app-level motion:
@media (prefers-reduced-motion: reduce) { .my-panel { transition-duration: 0ms; }}- Never gate function on motion. htmx swaps must land whether or not the transition plays — the kit’s transitions are all presentation-only, and yours should be too.
Using the scale in app CSS
Section titled “Using the scale in app CSS”.my-panel { transition: opacity var(--hc-motion-duration-base) var(--hc-motion-easing-enter);}Overriding the scale re-times every consumer at once:
:root { --hc-motion-duration-base: 160ms; /* a snappier app */}Related
Section titled “Related”- Tokens — how the token layers emit custom properties.
- Accessibility — reduced-motion testing.