Animations for Libra
With proper animations, any product can feel more qualitative, faster, and more predictable. But they can also do the opposite: slow down users, annoy them, and induce uncertainty.
Adding animations may feel like a reasonable idea, but we should always ask: Is adding this animation going to help or distract the user?
Animations must earn their place
There are only three good reasons to animate something:
- Feedback – confirming that an action registered
- Orientation – showing where something came from or went
- Focus – drawing attention to a change the user would otherwise miss
If an animation does none of these, it is decoration. Decoration is fine on a landing page — in a tool people use daily, it is a tax they pay on every interaction. Sometimes the best animation is no animation.
Frequency
Think about what the user wants to achieve and how often they will see an animation. A hover effect is nice, but if used multiple times a day, it would likely benefit the most from having no animation at all.
A rule of thumb: the more often an action is performed, the less it should animate. Something seen once (onboarding, a success moment) can afford expressive motion. Something used dozens of times a day (switching tabs, expanding rows, a command palette) should be instant. And never animate in response to keyboard input — keyboard users are your fastest users, and any transition makes the UI feel like it is lagging behind them.
What not to animate
High-frequency, goal-oriented actions: tab switches, list navigation, autocomplete, frequently used panels. Text content the user is waiting to read — don’t fade in search results, they want the data, not a reveal. And consecutive identical elements: the first tooltip in a group may fade in after a delay, but moving to the next one should show it instantly.
What should be animated
Overlays entering and exiting (modals, popovers, toasts) — sudden appearance is jarring, and motion clarifies where the element came from. Elements appearing or disappearing inside a layout — without a collapse, content teleports and users lose their place. State changes on the same element, loading indicators, and changes that happen outside where the user is currently looking.
Animated (200ms)
Instant
Origin
An animation should always depict where an element is coming from — and, on exit, where it returns to. A menu grows out of the button that opened it, a side panel slides in from the edge it lives at, a toast rises from the corner it rests in. When motion matches spatial reality, users build a mental model of where things live in the interface; when a popover blooms from its own center, the motion tells them nothing.
In practice this means setting transform-origin to the trigger, not the element’s center — Bits UI exposes it as a CSS variable like --bits-floating-transform-origin — sliding panels from their anchored edge, and letting dismissed elements exit toward the place that summoned them.
Duration
Stay under 300ms for almost everything; 150–250ms is the sweet spot for UI transitions, and hover or color changes should be around 100–150ms. Scale duration with size and distance: a checkbox tick takes 100ms, a full-height panel can take 250ms — same perceived speed, different durations. When in doubt, make it faster. Nobody has ever complained that a dropdown opened too quickly.
Easing
Pick easing by what the element is doing. Entering or exiting the screen: ease-out, so the UI responds immediately and settles gently. Moving while staying on screen: ease-in-out. Hover and color transitions: ease. Never linear for UI (spinners excepted), and almost never ease-in on its own — it makes the start feel sluggish, exactly where responsiveness matters most.
Craft details
Never animate from scale(0) — start at 0.9–0.97 with a fade instead. Exits should be faster than entrances: the user asked for the thing to go away, so get out of the way. Animate only transform and opacity so frequent animations never jank, and every animation must be interruptible — never block input while something moves.
Press feedback is the cheapest win of all: a subtle scale-down on active makes any control feel physical, with no JavaScript at all.
Accessibility
Respect prefers-reduced-motion: every animation needs a reduced variant, usually a fast fade or nothing at all. And motion must never be the only carrier of information — pair it with a state that persists, like a color, icon, or label change.
A checklist before shipping any animation
Does it give feedback, orient, or direct focus — or is it decoration? Will users see it twenty times a day? Is it keyboard-triggered? Is it under 300ms with the right easing? Does its motion depict where the element comes from? Does it only touch transform and opacity, and can it be interrupted? Does it degrade under reduced motion?
If an animation survives all of that, ship it. Most won’t — and that’s the point. The product will feel faster and more polished with ten deliberate animations than with a hundred reflexive ones.