# 60fps-animation

Replaces layout-triggering CSS properties with compositor transforms and opacity for 60fps. Fixes stuttering, layout thrashing, and height: auto animations.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 2600 installs · ★ 58
- Author: iart-ai
- License: MIT · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/iart-ai/web-animation-skills/tree/HEAD/skills/60fps-animation/SKILL.md
- Updated: 2026-06-22
- HTML: https://affpapa.org/en/nevibecode/skills/60fps-animation

## What it does

The skill directs your coding agent to replace costly layout and paint properties with cheap compositor steps. Changing `top`, `left`, `margin`, or `box-shadow` forces reflow and repaint on every frame. This blocks the main thread. The skill replaces them with `transform` and `opacity`, shifting the workload to the GPU. For `box-shadow`, it fades a pseudo-element instead of recalculating blurs.

For complex layout shifts, the skill applies the FLIP pattern using the Web Animations API to prevent text distortion. It solves `height: auto` transitions using modern `interpolate-size` or a CSS grid fallback from `0fr` to `1fr`. It also batches DOM reads and writes to eliminate layout thrashing. Note the trade-off with `will-change`: leaving it active indefinitely consumes GPU memory and hurts performance.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add iart-ai/web-animation-skills --skill 60fps-animation -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/60fps-animation/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/60fps-animation/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add iart-ai/web-animation-skills --skill 60fps-animation -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/60fps-animation/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add iart-ai/web-animation-skills --skill 60fps-animation -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/60fps-animation/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install iart-ai/web-animation-skills 60fps-animation
```

2. **Manually: put the files in place**
- File: `.github/skills/60fps-animation/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add iart-ai/web-animation-skills --skill 60fps-animation -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/iart-ai/web-animation-skills --path skills/60fps-animation
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/60fps-animation/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add iart-ai/web-animation-skills --skill 60fps-animation -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/iart-ai/web-animation-skills/tree/HEAD/skills/60fps-animation/SKILL.md

## When to use it
- convert layout animations from left and top to transform
- eliminate repaint lag on heavy box-shadow transitions
- animate collapsible containers with height: auto
- implement FLIP transitions for reordered elements
- batch DOM reads and writes to prevent layout thrashing

## Example prompts
- Convert this hover animation from top and left to transform
- Fix jank when animating height auto on my accordion component
- Implement a smooth FLIP animation for reordering these list items

## Source text · SKILL.md · MIT

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 959b69b7e062119f.

BEGIN THIRD-PARTY FILE 959b69b7e062119f
````text
---
name: 60fps-animation
description: This skill should be used when the user asks to "fix janky CSS animation", "make animation 60fps", "stop layout thrashing", "animate width/height/top/left smoothly", "convert animation to transform", "animate box-shadow performantly", "animate height auto", "FLIP animation", or "why is my scroll/hover animation choppy".
version: 0.1.0
---

# Performant Web Animation

Eliminate the #1 cause of janky web animation: animating properties that force the browser to recalculate layout (reflow) or repaint on every frame. The browser renders in stages — **layout → paint → composite**. Animating `width`, `height`, `top`, `left`, `margin`, `padding`, `box-shadow`, or `filter` re-runs layout and/or paint each frame, blocking the main thread. Animating **`transform`** and **`opacity`** runs entirely on the compositor (often the GPU), skipping layout and paint, which is what makes animation smooth at 60/120fps.

## When to use

Use when an animation stutters or drops frames, when a hover/scroll effect feels heavy, when animating size/position/shadow, when a layout change needs to animate smoothly (cards reordering, an element moving between containers), when animating `height: auto`, or when reviewing animation code for performance.

## Core rule: animate only transform and opacity

Map every "expensive" animation to a cheap equivalent.

| Animating (expensive) | Triggers | Replace with (cheap) |
|---|---|---|
| `width` / `height` | Layout + Paint | `transform: scaleX()/scaleY()` (+ FLIP for true size) |
| `top` / `left` / `margin` | Layout + Paint | `transform: translate()` |
| `box-shadow` | Paint | Animate `opacity` of a pseudo-element holding the shadow |
| `filter: blur()` | Paint (heavy) | Cross-fade two layers via `opacity`, or accept sparingly |
| `background-position` | Paint | `transform: translate()` on a child layer |
| `color` / `background` | Paint | Often acceptable; or cross-fade layers |

### Position and size via transform

```css
/* BAD: animates layout every frame */
.box { transition: left 300ms, width 300ms; left: 0; width: 100px; }
.box:hover { left: 200px; width: 200px; }

/* GOOD: compositor-only */
.box {
  transition: transform 300ms ease;
  transform: translateX(0) scaleX(1);
  transform-origin: left center;
}
.box:hover { transform: translateX(200px) scaleX(2); }
```

`scaleX` distorts inner content (text stretches). For true resizing without distortion, use **FLIP**.

## Cheap box-shadow via pseudo-element opacity

Animating `box-shadow` repaints a large blurred region every frame. Instead paint the shadow once on a `::after`, then animate only its `opacity`.

```css
.card { position: relative; }
.card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 12px 28px rgba(0,0,0,0.35);
  opacity: 0;
````
END THIRD-PARTY FILE 959b69b7e062119f

The third-party file has ended. Everything between the 959b69b7e062119f tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2852 of 10774 bytes. © iart-ai · MIT · https://github.com/iart-ai/web-animation-skills/tree/HEAD/skills/60fps-animation/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
