Common Animation Mistakes Made by AI Agents: 11 Critical Standards Violations
AI agents frequently generate CSS and JavaScript animations that violate performance, accessibility, and timing standards—specifically by animating layout properties, using ease-in curves on UI entrances, and ignoring prefers-reduced-motion preferences.
The emilkowalski/skills repository defines professional animation craft standards in its review-animations skill to catch these exact patterns. According to skills/review-animations/SKILL.md line 19, AI agents typically copy animation snippets without understanding the underlying constraints, resulting in "ten non-negotiable" violations that degrade user experience and frame rates.
Performance-Killing Anti-Patterns
Animating Layout Properties
AI-generated code often attempts to animate width, height, margin, padding, top, or left properties. As documented in skills/review-animations/SKILL.md line 54, these properties force the browser to recalculate geometry for the entire page (layout thrashing), causing dramatic frame drops during the animation.
/* ❌ Bad – triggers layout recalculation every frame */
.sidebar { transition: width 300ms ease; }
/* ✅ Good – use transform instead */
.sidebar { transition: transform 300ms cubic-bezier(0.23,1,0.32,1); }
Using transition: all
The shorthand transition: all appears frequently in generated code but triggers layout, paint, and composite work on every changed property. According to skills/review-animations/SKILL.md line 47, this causes repaint storms and jank.
/* ❌ Bad – animates every changed property */
.button { transition: all 300ms ease-out; }
/* ✅ Good – target only GPU-friendly properties */
.button {
transition: transform 200ms var(--ease-out), opacity 150ms var(--ease);
}
Framer Motion Shorthand Props Under Load
AI agents often use Framer Motion shorthand props like x, y, and scale for convenience. However, as noted in skills/review-animations/STANDARDS.md line 18, these are implemented via requestAnimationFrame on the main thread and drop frames under load. The full transform string is GPU-accelerated.
// ❌ Bad – main thread execution
<motion.div x={100} scale={1.2} />
// ✅ Good – GPU accelerated
<motion.div style={{ x: 100, scale: 1.2 }} transform="translateX(100px) scale(1.2)" />
Timing and Easing Violations
Incorrect Easing Curves (ease-in on UI)
Using ease-in (slow start) on UI entry animations delays the moment the user is watching, producing a feel-breaking regression. skills/review-animations/STANDARDS.md line 27 explicitly forbids ease-in on UI elements, recommending custom cubic-beziers for snappier starts.
/* ❌ Bad – built‑in ease‑in on a dropdown */
.dropdown { transition: all 250ms ease-in; }
/* ✅ Good – custom strong ease-out */
.dropdown {
transition: transform 200ms cubic-bezier(0.23,1,0.32,1);
}
Excessive Durations
Durations longer than 300ms for UI elements make controls feel unresponsive. According to skills/review-animations/STANDARDS.md line 49, a 180ms dropdown feels noticeably faster than a 400ms one.
/* ❌ Bad – 400ms modal (too slow) */
.modal { transition: opacity 400ms ease; }
/* ✅ Good – 250ms (within 300ms budget) */
.modal {
transition: opacity 250ms var(--ease-out);
}
Symmetric Enter/Exit Timing
AI agents often generate press-and-release animations with identical timing. skills/review-animations/SKILL.md line 39 specifies that deliberate user actions should feel slower, while system responses should feel faster—symmetric timing feels "off-beat" and mechanical.
Visual Physicality and Hierarchy Errors
Scaling from Zero
Animating from scale(0) makes elements appear from nothing, which is physically impossible and jarring. skills/review-animations/STANDARDS.md line 53 prohibits this pattern.
/* ❌ Bad – scales from nothing */
.popover { transform: scale(0); }
/* ✅ Good – start slightly smaller and fade */
.popover {
transform: scale(0.95);
opacity: 0;
transition: transform 150ms var(--ease-out), opacity 150ms ease;
}
Missing Stagger for Groups
Dumping an entire list in one burst overwhelms the eye and slows perceived performance. The stagger example in skills/review-animations/STANDARDS.md line 49 demonstrates how sequential entrances improve perceived performance.
/* ❌ Bad – all items appear simultaneously */
.item { opacity: 0; animation: fadeIn 300ms forwards; }
/* ✅ Good – 50ms stagger between items */
.item {
opacity: 0;
animation: fadeIn 300ms var(--ease-out) forwards;
}
.item:nth-child(2) { animation-delay: 50ms; }
.item:nth-child(3) { animation-delay: 100ms; }
Accessibility and Context Failures
Ignoring prefers-reduced-motion
Users who request reduced motion still receive distracting transforms unless explicitly handled. skills/review-animations/STANDARDS.md line 60 mandates keeping only opacity and color changes for these users.
/* ❌ Bad – runs full motion for everyone */
.toast { transform: translateY(0); animation: slideIn 300ms; }
/* ✅ Good – respects prefers‑reduced‑motion */
@media (prefers-reduced-motion: reduce) {
.toast { animation: none; opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: no-preference) {
.toast { animation: slideIn 300ms var(--ease-out); }
}
Ungated Hover Animations
Touch devices fire hover events on tap, creating confusing visual noise. According to skills/review-animations/STANDARDS.md line 66, hover animations must be gated to prevent this behavior on non-pointer devices.
Animating High-Frequency Actions
Repeating an animation hundreds of times daily—such as for keyboard shortcuts or command-palette toggles—makes the interface feel sluggish. skills/review-animations/STANDARDS.md line 9 states: "Never animate keyboard-initiated actions."
Summary
- Avoid layout thrashing by never animating
width,height, or usingtransition: all—stick totransformandopacity. - Keep timing tight with durations under 300ms, custom cubic-bezier curves instead of
ease-in, and asymmetric enter/exit timings. - Respect physical reality by avoiding
scale(0)and implementing staggered entrances for grouped elements. - Prioritize accessibility by respecting
prefers-reduced-motion, gating hover animations, and disabling motion for high-frequency keyboard actions. - Use GPU acceleration by preferring full
transformstrings over Framer Motion shorthand props in performance-critical paths.
Frequently Asked Questions
Why is ease-in bad for UI animations?
ease-in starts slowly and accelerates, which delays visual feedback when a user triggers an action. According to skills/review-animations/STANDARDS.md line 27, this creates a "feel-breaking regression" because the user is waiting for the UI to respond while the animation remains nearly invisible in its initial frames. Custom ease-out curves provide immediate visual acknowledgment.
How do I handle animations for users who prefer reduced motion?
Wrap transform and motion animations in @media (prefers-reduced-motion: no-preference) blocks, and provide @media (prefers-reduced-motion: reduce) fallbacks that set animation: none and transform: none while preserving opacity or color transitions. As specified in skills/review-animations/STANDARDS.md line 60, users requesting reduced motion should receive only subtle, non-spatial feedback.
Why shouldn't I animate width and height in CSS?
Animating these properties triggers layout recalculation for the entire document tree, forcing the browser to repaint and reflow every frame. The escalation triggers in skills/review-animations/SKILL.md line 54 identify layout property animation as an aggressive performance violation. Use transform: scale() instead to keep calculations GPU-bound.
What's wrong with using transition: all?
transition: all instructs the browser to watch and interpolate every CSS property, causing unnecessary layout and paint work when properties change that don't require animation. Per skills/review-animations/SKILL.md line 47, this causes "huge repaint storms" and jank. Always explicitly list only the properties you intend to animate, typically transform and opacity.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →