Web animation css animations
Skill agents-inc/skills/dist/plugins/web-animation-css-animations/skills/web-animation-css-animations
The official skills marketplace for Agents Inc, an agent composition framework that builds stacks and compiles specialized subagents for Claude Code
npx -y skills add agents-inc/skills --skill web-animation-css-animationsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 18 stars18 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
CSS Animation patterns - transitions, keyframes, scroll-driven animations, @property, GPU-accelerated properties, accessibility with prefers-reduced-motion
SKILL.md
14.0 KB, as published. Nobody here has run it
CSS Animation Patterns
Quick Guide: Use CSS transitions for state changes (hover, focus),
@keyframesfor autonomous/looping animations, scroll-driven animations for scroll-linked effects. Animate onlytransformandopacityfor 60fps. Always respectprefers-reduced-motion.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST animate ONLY transform and opacity for GPU-accelerated 60fps performance)
(You MUST respect prefers-reduced-motion using @media (prefers-reduced-motion: no-preference) for opt-in or @media (prefers-reduced-motion: reduce) for opt-out)
(You MUST use CSS custom properties for ALL timing values - NO magic numbers like 0.3s)
(You MUST use ease-out for enter animations and ease-in for exit animations - NEVER linear for UI transitions)
(You MUST remove will-change after animation completes - permanent will-change wastes GPU memory)
</critical_requirements>
Auto-detection: CSS animation, CSS transition, @keyframes, transform, opacity, transition-duration, animation-duration, prefers-reduced-motion, scroll-timeline, animation-timeline, will-change, cubic-bezier, ease-out, ease-in, @property
When to use:
- Simple state change animations (hover, focus, active states)
- Autonomous looping animations (spinners, pulses, attention grabbers)
- Scroll-linked animations and parallax effects
- Micro-interactions that don't need JavaScript control
When NOT to use:
- Animations requiring JavaScript control (pause, reverse, seek) -- use Web Animations API
- Complex orchestrated animations with staggered timing -- use your animation library
- Physics-based spring animations -- use your animation library
- Drag-and-drop or gesture-driven animations -- use your animation library
Detailed Resources:
- examples/core.md - Token system, interactive states, shadows, loading, reduced motion
- examples/transitions.md - Multi-property transitions, accordions, color, links
- examples/keyframes.md - Scroll-driven, @property gradients, typewriter, stagger, shapes
- reference.md - Decision frameworks, timing reference, browser support
<philosophy>
Philosophy
CSS animations leverage the browser's compositor thread for smooth, 60fps animations that don't block JavaScript execution. By animating only GPU-accelerated properties (transform and opacity), animations run on a separate thread from the main JavaScript thread.
Core principles:
- Performance first - Animate only
transformandopacityto avoid layout/paint triggers - Accessibility built-in - Always respect
prefers-reduced-motionuser preferences - Transitions for state changes - Use CSS transitions for hover, focus, and state-driven animations
- Keyframes for autonomous motion - Use
@keyframesfor animations that loop, auto-play, or have multiple steps - Design tokens for consistency - Use CSS custom properties for durations, easings, and distances
<patterns>
Core Patterns
Pattern 1: Animation Token System
Define timing, easing, and distance tokens as CSS custom properties for consistency. See examples/core.md for the full token setup.
:root {
--duration-instant: 100ms;
--duration-fast: 150ms;
--duration-normal: 250ms;
--duration-slow: 400ms;
--ease-out: cubic-bezier(0, 0, 0.2, 1); /* Enter */
--ease-in: cubic-bezier(0.4, 0, 1, 1); /* Exit */
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); /* Symmetric */
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* Bouncy */
--lift-sm: -2px;
--lift-md: -4px;
}
Why tokens matter: Consistent timing across application, easy to adjust globally, semantic naming communicates intent
Pattern 2: GPU-Accelerated Transitions
Only animate transform and opacity. Never animate layout properties like width, height, top, left, margin, or padding.
/* CORRECT - GPU-accelerated */
.card {
transition:
transform var(--duration-fast) var(--ease-out),
opacity var(--duration-fast) var(--ease-out);
}
.card:hover {
transform: translateY(var(--lift-md)) scale(1.02);
}
/* WRONG - triggers layout recalculation every frame */
.card {
transition: all 0.3s linear;
}
.card:hover {
top: -8px;
margin-top: -8px;
}
Transform mapping: Use translate() instead of top/left, scale() instead of width/height, pseudo-element opacity instead of box-shadow.
See examples/core.md for button states, card hover effects, and the pseudo-element shadow technique.
Pattern 3: Prefers-Reduced-Motion
Every animation must respect user motion preferences. Two strategies:
Progressive Enhancement (Recommended)
/* Base: no motion */
.element {
opacity: 1;
transform: translateY(0);
}
/* Opt-in to motion */
@media (prefers-reduced-motion: no-preference) {
.element {
animation: fade-slide-in var(--duration-normal) var(--ease-out);
}
}
Graceful Degradation
.notification {
animation: slide-in-bounce var(--notification-duration) var(--ease-spring);
}
@media (prefers-reduced-motion: reduce) {
.notification {
animation: fade-in calc(var(--notification-duration) * 0.5) var(--ease-out);
}
}
Key insight: Reduced motion does not mean no animation. Opacity fades are generally safe. Replace spatial movement with opacity-only alternatives.
See examples/core.md for the complete reduced motion pattern.
Pattern 4: CSS @keyframes
Use @keyframes for animations that loop, auto-play on mount, or have more than two states.
@keyframes fade-slide-in {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.modal {
--modal-enter-duration: 300ms;
animation: fade-slide-in var(--modal-enter-duration) var(--ease-out) forwards;
}
Key details:
- Use
forwardsfill mode to retain final state after animation - Use
backwardsfill mode to show initial state duringanimation-delay - Use
ease-outfor enter,ease-infor exit linearis only appropriate for continuous rotation (spinners)
See examples/core.md for spinners, pulses, skeleton loaders, and toast animations. See examples/keyframes.md for scroll-driven animations, @property gradients, and complex sequences.
Pattern 5: Will-Change Optimization
will-change creates a GPU layer (~307KB per 320x240px element). Apply only when needed, remove after.
/* CORRECT - only during interaction */
.card:hover {
will-change: transform;
}
/* WRONG - permanent GPU layer on every element */
* {
will-change: transform;
}
Never apply will-change permanently. Each element with will-change creates a separate compositing layer that consumes GPU memory. On mobile devices, this can crash the browser.
Pattern 6: Scroll-Driven Animations
CSS animation-timeline allows scroll-linked animations without JavaScript.
.progress-bar {
animation: grow-width linear;
animation-timeline: scroll();
}
@keyframes grow-width {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
Two timeline types:
scroll()-- progress based on scroll container positionview()-- progress based on element visibility in viewport
Browser support: Chrome/Edge 115+, Safari 26+, Firefox behind flag
See examples/keyframes.md for scroll progress, viewport reveal, and parallax patterns.
Pattern 7: @property for Custom Property Animation
CSS Houdini's @property enables animating custom properties like gradient angles that CSS cannot normally interpolate.
@property --gradient-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.gradient-border {
background: linear-gradient(var(--gradient-angle), #ff0080, #7928ca);
animation: rotate-gradient 3s linear infinite;
}
@keyframes rotate-gradient {
to {
--gradient-angle: 360deg;
}
}
Browser support: Chrome/Edge 85+, Safari 16.4+, Firefox 128+
</patterns><performance>
Performance
The 16.67ms Budget
For 60fps, each frame must complete in 16.67ms. Layout-triggering animations often exceed this budget.
| Category | Properties | Impact |
|---|---|---|
| Composite only (Best) | transform, opacity | No layout, no paint, GPU-accelerated |
| Paint only (Okay) | color, background-color, visibility | No layout, but repaints |
| Layout + Paint (Avoid) | width, height, margin, padding, top, left | Full page recalculation |
Duration Guidelines
| Animation Type | Duration | Reason |
|---|---|---|
| Micro-interactions | 100-150ms | Feels instant |
| UI transitions | 200-300ms | Sweet spot for perception |
| Page transitions | 300-500ms | Major context change |
| Complex sequences | 500-1000ms | Story-telling moments |
Transform Mapping
| Instead of... | Use... |
|---|---|
top, left | translate(x, y) |
width, height | scale() |
box-shadow | Pseudo-element with opacity |
margin, padding | translate() with layout space |
<decision_framework>
Decision Framework
Transitions vs @keyframes
Is the animation triggered by user interaction (hover, focus, class toggle)?
├─ YES → Is it a simple A->B state change?
│ ├─ YES -> CSS Transition
│ └─ NO -> Does it need multiple steps?
│ ├─ YES -> CSS @keyframes
│ └─ NO -> CSS Transition is fine
└─ NO -> Does it auto-play or loop?
├─ YES -> CSS @keyframes
└─ NO -> CSS Transition (triggered by class toggle)
Easing Selection
What type of motion?
├─ Element entering -> ease-out (fast start, slow end)
├─ Element exiting -> ease-in (slow start, fast end)
├─ Symmetric motion -> ease-in-out
├─ Continuous rotation -> linear
├─ Playful/bouncy -> custom cubic-bezier with overshoot
└─ Default UI -> ease-out
Never use:
├─ linear for UI transitions (feels robotic)
└─ ease (browser default) for production (too generic)
CSS vs JavaScript Animation
Does the animation need...
├─ Pause/play/reverse/seek control? -> JavaScript (Web Animations API)
├─ Dynamic values calculated at runtime? -> JavaScript or CSS custom properties
├─ Physics-based springs? -> Your animation library
├─ Orchestrated staggering across many elements? -> JavaScript for complex, CSS for simple
├─ Scroll-linked progress? -> CSS scroll-driven animations
├─ Page/view transitions? -> See the View Transitions skill
└─ Simple state transitions? -> CSS Transitions
</decision_framework>
<red_flags>
RED FLAGS
High Priority
- Animating layout properties (
width,height,top,left,margin,padding) -- triggers expensive reflows every frame; usetransforminstead - Magic numbers for timing (
0.3s,300msinline) -- all durations must be CSS custom properties - Missing
prefers-reduced-motion-- every animation must respect user preferences - Linear easing for UI transitions --
linearfeels robotic; useease-outfor enter,ease-infor exit - Permanent
will-change-- creates GPU layers permanently, wasting memory; apply only during animation
Medium Priority
- Using
transition: all-- transitions unnecessary properties, causes surprises when new properties are added - Animating
box-shadowdirectly -- causes repaint every frame; use pseudo-element with opacity - Missing
forwardson enter animations -- element snaps back to initial state - Very long durations (>1s) -- users perceive as slow; rarely appropriate outside special effects
Gotchas & Edge Cases
transform+position: fixed-- transform creates new containing block, breaking fixed positioning relative to viewportwill-changecreates stacking context -- can affect z-index behavior unexpectedly- Cannot animate
display: none-- useopacity+visibilityorgrid-template-rows: 0fr fill-mode: backwardsneeded for delayed animations -- without it, element shows in final state during delay- SVG uses different properties -- animate
stroke-dashoffsetandstroke-dasharray, nottransformfor path drawing - Scroll-driven animations need scrollable container --
overflow: hiddenparent breaksscroll-timeline - Print media -- animations don't print; ensure content is visible without animation
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md
(You MUST animate ONLY transform and opacity for GPU-accelerated 60fps performance)
(You MUST respect prefers-reduced-motion using @media (prefers-reduced-motion: no-preference) for opt-in or @media (prefers-reduced-motion: reduce) for opt-out)
(You MUST use CSS custom properties for ALL timing values - NO magic numbers like 0.3s)
(You MUST use ease-out for enter animations and ease-in for exit animations - NEVER linear for UI transitions)
(You MUST remove will-change after animation completes - permanent will-change wastes GPU memory)
Failure to follow these rules will cause jank, accessibility issues, and degraded user experience.
</critical_reminders>