# Hierarchy of Tools Recommended by the `animate` Skill: From CSS Transitions to Motion

> Discover the animate skill's tool hierarchy: CSS transitions, @starting-style, CSS animations, WAAPI, and Motion for powerful animations. Learn when to use each.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: tutorial
- Published: 2026-08-07

---

**The `animate` skill recommends five tools in escalating order of power: CSS transitions (simplest), CSS `@starting-style` for mount animations, CSS animations for main-thread resilience, WAAPI for programmatic control, and Motion (motion.dev) for springs, gestures, and layout animations.**

The `animate` skill in emilkowalski/skills provides a structured decision-making framework for adding motion to web interfaces. When you reach step 3—"Pick the tool — cheapest that works"—it presents a clear hierarchy designed to minimize performance overhead and avoid unnecessary dependencies. This article breaks down that hierarchy exactly as documented in [[`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md)](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md).

## The Five-Level Tool Hierarchy

The hierarchy progresses from zero-JavaScript solutions to full-featured libraries. Each level assumes the previous options failed to meet your specific need.

### Level 1: CSS Transition (Hover, Press, State Toggles)

**Use when:** You need to animate hover states, active presses, or any visual change controlled by a class or attribute change.

This is the cheapest option—no JavaScript, no parsing overhead, hardware-accelerated by default. The browser optimizes these automatically on the compositor thread.

```html
<button class="btn">Hover me</button>

<style>
.btn {
  background: #0066ff;
  transition: background 150ms ease;
}
.btn:hover {
  background: #0044aa;
}
</style>

```

**Key insight from the source:** CSS transitions sit at the foundation of the `animate` skill hierarchy because they trigger on computed value changes without any script execution.

### Level 2: CSS `@starting-style` (Entry Animations on Mount)

**Use when:** You need an entrance animation that fires when an element first appears, with no JavaScript state management.

The `@starting-style` at-rule lets you define the pre-mount state for an element, enabling pure-CSS mount animations without `useEffect` or `requestAnimationFrame` hacks.

```html
<div class="modal">…</div>

<style>
@starting-style {
  .modal {
    opacity: 0;
    transform: scale(0.95);
  }
}
.modal {
  animation: fadeIn 200ms ease-out forwards;
}
@keyframes fadeIn {
  to { opacity: 1; transform: scale(1); }
}
</style>

```

This pattern eliminates the flash-of-unstyled-content problem that previously forced developers toward JavaScript solutions.

### Level 3: CSS Animation (Resilient During Page Load)

**Use when:** You need predetermined motion that must stay smooth even when the main thread is blocked by JavaScript execution.

Unlike JavaScript-driven approaches, CSS animations run on a separate thread (the compositor). They continue smoothly while the page executes heavy scripts or parses large modules.

```css
.spinner {
  width: 24px;
  height: 24px;
  animation: spin 1s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

```

**Performance note:** This is the last purely declarative option in the hierarchy. Everything beyond this point requires JavaScript evaluation.

### Level 4: WAAPI (`element.animate()`)

**Use when:** You need programmatic control—dynamic durations, runtime-generated keyframes, or playback manipulation—while maintaining CSS-level performance.

The Web Animations API (WAAPI) provides imperative JavaScript control without shipping animation properties across the bundle. It uses the same browser engine as CSS animations, so performance characteristics match.

```javascript
const el = document.querySelector('.panel');
el.animate(
  [{ opacity: 0, transform: 'translateY(-10px)' },
   { opacity: 1, transform: 'translateY(0)' }],
  { duration: 180, easing: 'ease-out', fill: 'forwards' }
);

```

**Source reference:** In [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md) lines 63-70, WAAPI is positioned as the bridge between pure CSS and full libraries—offering JavaScript flexibility with zero dependency cost.

### Level 5: Motion (`motion.dev`)

**Use when:** You need physics-based springs, layout animations, exit animations, or gesture-driven values—features impossible in lower levels.

Motion (formerly Framer Motion) provides declarative React APIs for complex motion patterns. It handles layout projection, shared element transitions, and pointer-driven springs that would require thousands of lines of WAAPI code.

```tsx
import { motion } from 'motion';

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ type: 'spring', stiffness: 300, damping: 30 }}
/>

```

This is the only recommended dependency in the hierarchy. The `animate` skill explicitly reserves it for cases where native APIs cannot satisfy the requirement.

## How to Apply the Hierarchy in Practice

The `animate` skill encodes a specific decision flow. Before selecting any tool, verify that cheaper alternatives cannot solve your problem:

1. **Start with CSS transitions** for all state-based visual feedback
2. **Escalate to `@starting-style`** only when mounting needs animation
3. **Use CSS animations** when smoothness during load is critical
4. **Reach for WAAPI** when you need dynamic, script-controlled motion
5. **Add Motion** exclusively for springs, gestures, layout shifts, or exit animations

This progression prevents bundle bloat and maximizes runtime performance. The full reasoning appears in [[`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md)](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md), with concrete implementation patterns in [[`skills/animate/RECIPES.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/RECIPES.md)](https://github.com/emilkowalski/skills/blob/main/skills/animate/RECIPES.md).

## Summary

- **CSS transitions** handle the majority of UI motion needs with zero overhead
- **CSS `@starting-style`** enables mount animations without JavaScript state
- **CSS animations** guarantee smooth playback during main thread congestion
- **WAAPI** provides programmatic control matching CSS performance characteristics
- **Motion** resolves advanced requirements (springs, gestures, layout) that native APIs cannot address

## Frequently Asked Questions

### What order does the `animate` skill recommend for selecting animation tools?

The `animate` skill orders tools by cost and complexity: CSS transitions first, then CSS `@starting-style`, CSS animations, WAAPI, and finally Motion as the heavyweight solution. This sequence ensures you reach for dependencies only when native APIs prove insufficient.

### When should I use WAAPI instead of CSS animations?

Choose WAAPI when you need runtime-generated keyframes, dynamic duration changes, or playback control like `pause()` and `reverse()`. CSS animations require predefined keyframes in stylesheets—WAAPI constructs them in JavaScript while preserving the same thread-isolated performance.

### Why does CSS `@starting-style` exist as a separate step from transitions?

`@starting-style` solves a specific problem: styling the initial state of an element before it enters the DOM. Transitions only animate *changes* to existing elements. Without `@starting-style`, mount animations previously required JavaScript to force a reflow or state management to delay visibility—now handled declaratively in CSS.

### Is Motion always necessary for React animations?

No—according to the `animate` skill hierarchy, Motion is specifically reserved for springs, layout animations, exit animations, and gesture-driven values. Simple fades, slides, and state changes should use CSS transitions or WAAPI to avoid the dependency cost and runtime overhead of a full motion library.