auto-animate
Install this skill
npx skills add jezweb/claude-skillsWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
AutoAnimate manages DOM transitions by automatically monitoring child additions, removals, and positional changes. By applying a single reference hook to a container element, the library tracks the layout state and injects hardware-accelerated CSS animations whenever the DOM tree updates. It eliminates the need for manual keyframe definitions, state-based animation libraries, or complex exit/enter transition configurations. The tool functions by detecting structural mutations within the parent container and performing calculations to glide elements into their new positions. While effective for simple UI changes, it requires careful handling of SSR environments, strict adherence to unique key management in lists, and specific layout constraints for flexbox containers. This tool bridges the gap between static content and dynamic interfaces with minimal configuration overhead, assuming developers avoid common pitfalls related to DOM ref attachment.
When to Use This Skill
- β’Animating filtering or sorting operations in user-facing lists
- β’Adding visual feedback for dynamic inventory or cart adjustments
- β’Smooth transitions for expanding or collapsing UI sections
- β’Handling layout shifts when removing or inserting navigation menu items
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- βMake my list items animate when they are removed
- βAdd transition effects to my React list
- βHow to make my sorting list move smoothly
- βAutoAnimate setup for my Next.js project
- βFix layout jumping when adding elements to a list
Pro Tips
- π‘Always utilize the `useAutoAnimateSafe` pattern provided for any SSR-capable framework (like Next.js) to avoid critical runtime errors, even if you don't explicitly think you're rendering on the server.
- π‘Before diving into complex custom animations, test auto-animate's default behavior with a simple list to confirm it integrates correctly with your component's lifecycle and state management.
- π‘For advanced debugging, combine this skill's insights with your browser's dev tools to inspect element styles and ensure auto-animate is correctly applying its CSS transforms, especially when encountering visual glitches.
What this skill does
- β’Automatic hardware-accelerated layout transitions
- β’Zero-configuration entry and exit animation management
- β’Dynamic detection of list item reordering
- β’Support for conditional DOM rendering without manual keyframes
- β’Compatibility across React, Vue, Svelte, and Solid frameworks
When not to use it
- βComplex, multi-stage or orchestrated sequencing animations
- βApplications requiring precise control over easing curves and timing offsets
- βEnvironments where the DOM is manually manipulated outside the framework lifecycle
Example workflow
- Install @formkit/auto-animate as a dependency
- Create a hook or directive wrapper to ensure SSR safety
- Attach the reference provided by the hook to the parent list container
- Ensure each list item contains a stable and unique key prop
- Define fixed widths for flex children to prevent layout shaking
- Verify the animation flow by toggling list visibility state
Prerequisites
- βNode.js environment
- βA supported framework like React or Vue
- βBasic understanding of DOM references
Pitfalls & limitations
- !Conditional rendering of the parent container prevents the animation from attaching correctly
- !Flexbox items with dynamic sizing cause container jitter during removal
- !Server-side rendering environments trigger import errors if accessed during initial load
FAQ
How it compares
Unlike manual CSS transitions or libraries like Framer Motion, AutoAnimate requires zero code to define the actual movement, automating the entire process based on DOM mutations.
π Full skill instructions β original source: jezweb/claude-skills
**Package**: @formkit/[email protected] (current)
**Frameworks**: React, Vue, Solid, Svelte, Preact
**Last Updated**: 2026-01-21
---
## SSR-Safe Pattern (Critical for Cloudflare Workers/Next.js)
// Use client-only import to prevent SSR errors
import { useState, useEffect } from "react";
export function useAutoAnimateSafe<T extends HTMLElement>() {
const [parent, setParent] = useState<T | null>(null);
useEffect(() => {
if (typeof window !== "undefined" && parent) {
import("@formkit/auto-animate").then(({ default: autoAnimate }) => {
autoAnimate(parent);
});
}
}, [parent]);
return [parent, setParent] as const;
}**Why this matters**: Prevents Issue #1 (SSR/Next.js import errors). AutoAnimate uses DOM APIs not available on server.
---
## Known Issues Prevention (15 Documented Errors)
This skill prevents **15** documented issues:
### Issue #1: SSR/Next.js Import Errors
**Error**: "Can't import the named export 'useEffect' from non EcmaScript module"
**Source**: https://github.com/formkit/auto-animate/issues/55
**Why It Happens**: AutoAnimate uses DOM APIs not available on server
**Prevention**: Use dynamic imports (see
templates/vite-ssr-safe.tsx)### Issue #2: Conditional Parent Rendering
**Error**: Animations don't work when parent is conditional
**Source**: https://github.com/formkit/auto-animate/issues/8
**Why It Happens**: Ref can't attach to non-existent element
**Prevention**:
**React Pattern**:
// β Wrong
{showList && <ul ref={parent}>...</ul>}
// β
Correct
<ul ref={parent}>{showList && items.map(...)}</ul>**Vue.js Pattern**:
<!-- β Wrong - parent conditional -->
<ul v-if="showList" ref="parent">
<li v-for="item in items" :key="item.id">{{ item.text }}</li>
</ul>
<!-- β
Correct - children conditional -->
<ul ref="parent">
<li v-if="showList" v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</ul>**Source**: React [Issue #8](https://github.com/formkit/auto-animate/issues/8), Vue [Issue #193](https://github.com/formkit/auto-animate/issues/193)
### Issue #3: Missing Unique Keys
**Error**: Items don't animate correctly or flash
**Source**: Official docs
**Why It Happens**: React can't track which items changed
**Prevention**: Always use unique, stable keys (
key={item.id})### Issue #4: Flexbox Width and Shaking Issues
**Error**: Elements snap to width instead of animating smoothly, or container shakes on remove
**Source**: Official docs, [Issue #212](https://github.com/formkit/auto-animate/issues/212)
**Why It Happens**:
flex-grow: 1 waits for surrounding content, causing timing issues**Prevention**: Use explicit width instead of flex-grow for animated elements
// β Wrong - causes shaking
<ul ref={parent} style={{ display: 'flex' }}>
{items.map(item => (
<li key={item.id} style={{ flex: '1 1 auto' }}>{item.text}</li>
))}
</ul>
// β
Correct - fixed sizes
<ul ref={parent} style={{ display: 'flex', gap: '1rem' }}>
{items.map(item => (
<li
key={item.id}
style={{ minWidth: '200px', maxWidth: '200px' }}
>
{item.text}
</li>
))}
</ul>**Maintainer Note**: justin-schroeder confirmed fixed sizes are required for flex containers
### Issue #5: Table Row Display Issues
**Error**: Table structure breaks when removing rows
**Source**: https://github.com/formkit/auto-animate/issues/7
**Why It Happens**: Display: table-row conflicts with animations
**Prevention**: Apply to
<tbody> instead of individual rows, or use div-based layouts### Issue #6: Jest Testing Errors
**Error**: "Cannot find module '@formkit/auto-animate/react'"
**Source**: https://github.com/formkit/auto-animate/issues/29
**Why It Happens**: Jest doesn't resolve ESM exports correctly
**Prevention**: Configure
moduleNameMapper in jest.config.js### Issue #7: esbuild Compatibility
**Error**: "Path '.' not exported by package"
**Source**: https://github.com/formkit/auto-animate/issues/36
**Why It Happens**: ESM/CommonJS condition mismatch
**Prevention**: Configure esbuild to handle ESM modules properly
### Issue #8: CSS Position Side Effects
**Error**: Layout breaks after adding AutoAnimate
**Source**: Official docs
**Why It Happens**: Parent automatically gets
position: relative**Prevention**: Account for position change in CSS or set explicitly
### Issue #9: Vue/Nuxt Registration Errors
**Error**: "Failed to resolve directive: auto-animate"
**Source**: https://github.com/formkit/auto-animate/issues/43
**Why It Happens**: Plugin not registered correctly
**Prevention**: Proper plugin setup in Vue/Nuxt config (see references/)
**Nuxt 3 Note**: Requires v0.8.2+ (April 2024). Earlier versions have ESM import issues fixed by Daniel Roe. See [Issue #199](https://github.com/formkit/auto-animate/issues/199)
### Issue #10: Angular ESM Issues
**Error**: Build fails with "ESM-only package"
**Source**: https://github.com/formkit/auto-animate/issues/72
**Why It Happens**: CommonJS build environment
**Prevention**: Configure ng-packagr for Angular Package Format
### Issue #11: React 19 StrictMode Double-Call Bug
**Error**: Child animations don't work in React 19 StrictMode
**Source**: https://github.com/formkit/auto-animate/issues/232
**Why It Happens**: StrictMode calls useEffect twice, triggering autoAnimate initialization twice
**Prevention**: Use ref to track initialization
// β Wrong - breaks in StrictMode
const [parent] = useAutoAnimate();
// β
Correct - prevents double initialization
const [parent] = useAutoAnimate();
const initialized = useRef(false);
useEffect(() => {
if (initialized.current) return;
initialized.current = true;
}, []);**Note**: React 19 enables StrictMode by default in development. This affects all React 19+ projects.
### Issue #12: Broken Animation Outside Viewport
**Error**: Animations broken when list is outside viewport
**Source**: https://github.com/formkit/auto-animate/issues/222
**Why It Happens**: Chrome may not run Animation API for off-screen elements
**Prevention**: Ensure parent is visible before applying autoAnimate
const isInViewport = (element) => {
const rect = element.getBoundingClientRect();
return rect.top >= 0 && rect.bottom <= window.innerHeight;
};
useEffect(() => {
if (parent.current && isInViewport(parent.current)) {
autoAnimate(parent.current);
}
}, [parent]);### Issue #13: Deleted Elements Overlay Existing Content
**Error**: Removed items overlay other items during fade out
**Source**: https://github.com/formkit/auto-animate/issues/231
**Why It Happens**: Exit animation maintains z-index, covering active content
**Prevention**: Add explicit z-index handling
// CSS workaround
<style>{
[data-auto-animate-target] {
z-index: -1 !important;
}
}</style>### Issue #14: Cannot Disable During Drag & Drop
**Error**: Calling enable(false) doesn't prevent animations during drag
**Source**: https://github.com/formkit/auto-animate/issues/215
**Why It Happens**: Disable doesn't work reliably mid-drag
**Prevention**: Conditionally remove ref during drag
const [isDragging, setIsDragging] = useState(false);
const [parent] = useAutoAnimate();
return (
<ul ref={isDragging ? null : parent}>
{/* items */}
</ul>
);### Issue #15: CSS Transform Parent Position Bug
**Error**: Items animate from wrong position after parent transform
**Source**: https://github.com/formkit/auto-animate/issues/227
**Why It Happens**: Items remember original position before transform
**Prevention**: Delay autoAnimate until transform completes
useEffect(() => {
if (showList && parent.current) {
setTimeout(() => {
autoAnimate(parent.current);
}, 300); // Match CSS transition duration
}
}, [showList]);---
## Critical Rules (Error Prevention)
### Always Do
β **Use unique, stable keys** -
key={item.id} not key={index}β **Keep parent in DOM** - Parent ref element always rendered
β **Client-only for SSR** - Dynamic import for server environments
β **Respect accessibility** - Keep
disrespectUserMotionPreference: falseβ **Test with motion disabled** - Verify UI works without animations
β **Use explicit width** - Avoid flex-grow on animated elements
β **Apply to tbody for tables** - Not individual rows
### Never Do
β **Conditional parent** -
{show && <ul ref={parent}>}β **Index as key** -
key={index} breaks animationsβ **Ignore SSR** - Will break in Cloudflare Workers/Next.js
β **Force animations** -
disrespectUserMotionPreference: true breaks accessibilityβ **Animate tables directly** - Use tbody or div-based layout
β **Skip unique keys** - Required for proper animation
β **Complex animations** - Use Motion instead
**Note**: AutoAnimate respects
prefers-reduced-motion automatically (never disable this).---
## Community Tips (Community-Sourced)
> **Note**: These tips come from community discussions. Verify against your version.
### Tip: Prevent Test Freezing with Mocked Package
**Source**: [Issue #230](https://github.com/formkit/auto-animate/issues/230) | **Confidence**: MEDIUM
**Applies to**: v0.8.2+
Tests may freeze for ~10 seconds when package is mocked. Add ResizeObserver mock:
// jest.setup.js
global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));
// __mocks__/@formkit/auto-animate.js
const autoAnimate = jest.fn(() => () => {});
const useAutoAnimate = jest.fn(() => [null, jest.fn(), jest.fn()]);
module.exports = { default: autoAnimate, useAutoAnimate };### Tip: Memory Leak Prevention
**Source**: [Issue #180](https://github.com/formkit/auto-animate/issues/180) | **Confidence**: LOW
**Applies to**: All versions
For long-lived SPAs, ensure proper cleanup:
useEffect(() => {
const cleanup = autoAnimate(parent.current);
return () => cleanup && cleanup();
}, []);
// useAutoAnimate hook handles cleanup automatically
const [parent] = useAutoAnimate(); // Preferred---
## Package Versions
**Latest**: @formkit/[email protected] (Sept 5, 2025)
**Recent Releases**:
- v0.9.0 (Sept 5, 2025) - Current stable
- v0.8.2 (April 10, 2024) - Fixed Nuxt 3 ESM imports, ResizeObserver guard
{
"dependencies": {
"@formkit/auto-animate": "^0.9.0"
}
}**Framework Compatibility**: React 18+, Vue 3+, Solid, Svelte, Preact
**Important**: For Nuxt 3 users, v0.8.2+ is required. Earlier versions have ESM import issues
---
## Official Documentation
- **Official Site**: https://auto-animate.formkit.com
- **GitHub**: https://github.com/formkit/auto-animate
- **npm**: https://www.npmjs.com/package/@formkit/auto-animate
- **React Docs**: https://auto-animate.formkit.com/react
---
## Templates & References
See bundled resources:
-
templates/ - Copy-paste examples (SSR-safe, accordion, toast, forms)-
references/ - CSS conflicts, SSR patterns, library comparisonsHow to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/auto-animate/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/jezweb/claude-skills/auto-animate/SKILL.md - Cursor:
~/.cursor/skills/jezweb/claude-skills/auto-animate/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/jezweb/claude-skills/auto-animate/SKILL.md
π Install with CLI:npx skills add jezweb/claude-skills
