--- name: animation-best-practices description: CSS and UI animation patterns for responsive, polished interfaces. Use when implementing hover effects, tooltips, button feedback, transitions, or fixing animation issues like flicker and shakiness. version: 1.0.0 --- # Practical Animation Tips Detailed reference guide for common animation scenarios. Use this as a checklist when implementing animations. ## Recording & Debugging ### Record Your Animations When something feels off but you can't identify why, record the animation and play it back frame by frame. This reveals details invisible at normal speed. ### Fix Shaky Animations Elements may shift by 1px at the start/end of CSS transform animations due to GPU/CPU rendering handoff. **Fix:** ```css .element { will-change: transform; } ``` This tells the browser to keep the element on the GPU throughout the animation. ### Take Breaks Don't code and ship animations in one sitting. Step away, return with fresh eyes. The best animations are reviewed and refined over days, not hours. ## Button & Click Feedback ### Scale Buttons on Press Make interfaces feel responsive by adding subtle scale feedback: ```css button:active { transform: scale(0.97); } ``` This gives instant visual feedback that the interface is listening. ### Don't Animate from scale(0) Starting from `scale(0)` makes elements appear from nowhere—it feels unnatural. **Bad:** ```css .element { transform: scale(0); } .element.visible { transform: scale(1); } ``` **Good:** ```css .element { transform: scale(0.95); opacity: 0; } .element.visible { transform: scale(1); opacity: 1; } ``` Elements should always have some visible shape, like a deflated balloon. ## Tooltips & Popovers ### Skip Animation on Subsequent Tooltips First tooltip: delay + animation. Subsequent tooltips (while one is open): instant, no delay. ```css .tooltip { transition: transform 125ms ease-out, opacity 125ms ease-out; transform-origin: var(--transform-origin); } .tooltip[data-starting-style], .tooltip[data-ending-style] { opacity: 0; transform: scale(0.97); } /* Skip animation for subsequent tooltips */ .tooltip[data-instant] { transition-duration: 0ms; } ``` Radix UI and Base UI support this pattern with `data-instant` attribute. ### Make Animations Origin-Aware Popovers should scale from their trigger, not from center. ```css /* Default (wrong for most cases) */ .popover { transform-origin: center; } /* Correct - scale from trigger */ .popover { transform-origin: var(--transform-origin); } ``` **Radix UI:** ```css .popover { transform-origin: var(--radix-dropdown-menu-content-transform-origin); } ``` **Base UI:** ```css .popover { transform-origin: var(--transform-origin); } ``` ## Speed & Timing ### Keep Animations Fast A faster-spinning spinner makes apps feel faster even with identical load times. A 180ms select animation feels more responsive than 400ms. **Rule:** UI animations should stay under 300ms. ### Don't Animate Keyboard Interactions Arrow key navigation, keyboard shortcuts—these are repeated hundreds of times daily. Animation makes them feel slow and disconnected. **Never animate:** - List navigation with arrow keys - Keyboard shortcut responses - Tab/focus movements ### Be Careful with Frequently-Used Elements A hover effect is nice, but if triggered multiple times a day, it may benefit from no animation at all. **Guideline:** Use your own product daily. You'll discover which animations become annoying through repeated use. ## Hover States ### Fix Hover Flicker When hover animation changes element position, the cursor may leave the element, causing flicker. **Problem:** ```css .box:hover { transform: translateY(-20%); } ``` **Solution:** Animate a child element instead: ```html