Skip to content
Development
Skill

/web-animation-view-transitions

View Transitions API patterns - same-document transitions, cross-document navigation, shared element animations, pseudo-element styling, transition types, reduced-motion handling

From plugin
agents-inc-skills
24200 skills
Install
$ npx -y skills add agents-inc/skills --skill web-animation-view-transitions --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/web-animation-view-transitions

Context preview

The summary Claude sees to decide when to auto-load this skill.

View Transitions API patterns - same-document transitions, cross-document navigation, shared element animations, pseudo-element styling, transition types, reduced-motion handling

SKILL.md

web-animation-view-transitions.SKILL.md
name: web-animation-view-transitions
description: View Transitions API patterns - same-document transitions, cross-document navigation, shared element animations, pseudo-element styling, transition types, reduced-motion handling

View Transitions API Patterns

> **Quick Guide:** The browser screenshots the old state, holds the new one live, and animates > between them as a tree of pseudo-elements. `document.startViewTransition()` drives a same-document > change; `@view-transition { navigation: auto }` on both pages drives a cross-document one. > `view-transition-name` pulls an element out of the root snapshot so it can travel on its own, and > the whole animation is customised in CSS rather than in script.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — feature detection, state transitions, the three promises, skipping, CSS overrides
  • [examples/spa.md](examples/spa.md) — theme reveal, form steps, tab panels, accordions, list reordering, reduced motion
  • [examples/shared-elements.md](examples/shared-elements.md) — hero animations, multi-element cards, cross-document pairs, modals
  • [reference.md](reference.md) — naming rules, pseudo-element tree, browser support, API tables

---

Which path applies

  • **Client routing or in-page state, with the DOM updated by script** — `startViewTransition()` takes

the update as a callback and captures around it; follow [examples/spa.md](examples/spa.md).

  • **Server-rendered pages navigating to each other** — no script at all: both documents opt in with

`@view-transition { navigation: auto }`, and names are set through the `pageswap` and `pagereveal` events; follow [examples/shared-elements.md](examples/shared-elements.md).

  • **One element has to travel between the two states rather than cross-fade with everything else** —

it needs a `view-transition-name` matched on both sides; follow [examples/shared-elements.md](examples/shared-elements.md).

---

<critical_requirements>

Before writing View Transitions code

**Guard `startViewTransition` behind a support check, and run the update either way.** The call is absent rather than inert where the API is unimplemented, so an unguarded call throws and the DOM change never happens at all.

**Give each participating element a name no other visible element carries.** The name identifies one snapshot; two visible elements claiming the same one abort the whole transition, not just their own part of it.

**Clear a dynamically assigned `view-transition-name` once `transition.finished` resolves.** A name left on an element collides with the next transition that assigns it, which is why the failure shows up on the second navigation rather than the first.

**Give every customised transition a `prefers-reduced-motion` branch.** A page-level transition moves the entire viewport, which is the class of motion the preference exists for; collapse the duration or skip the transition and apply the update directly.

</critical_requirements>

---

**Auto-detection:** startViewTransition, view-transition-name, view-transition-class, @view-transition, ::view-transition-old, ::view-transition-new, ::view-transition-group, ::view-transition-image-pair, :active-view-transition-type, pageswap, pagereveal, updateCallbackDone, skipTransition, match-element

**Applies to:**

  • State changes large enough that the whole view, or a large region of it, is replaced
  • Page-to-page navigation in server-rendered sites
  • Hero animations where one element persists across two views
  • Direction-aware navigation, where forward and back need opposite motion
  • Reordering, where elements move rather than change

**Handled elsewhere:**

  • Hover, focus and pressed feedback on a single control — nothing is being replaced, so there is no

before-and-after pair to capture

  • Motion whose velocity carries across an interruption, such as a spring picked up mid-gesture
  • Frame-level timeline authoring, where the deliverable is a scrubbable timeline

---

<philosophy>

A view transition is a screenshot and a live view, animated against each other. Everything follows from that: the old side is inert pixels, so anything moving inside it freezes; naming an element lifts it into its own snapshot pair with its own animation; and the whole tree is styled with CSS because it is a tree of pseudo-elements, not a script-driven animation.

The DOM update itself stays ordinary. `startViewTransition` wraps a change that would have happened anyway, which is why the fallback for an unsupported browser is simply making the change.

</philosophy>

---

<decision_framework>

Which snapshot the element belongs to

Does an element exist on both sides and represent the same thing?
├─ YES -> give it one view-transition-name on both sides; it gets its own group and travels
└─ NO  -> leave it in the root snapshot; it cross-fades with everything else around it

Each named element adds a group, an image pair and two snapshots to the tree, so naming everything costs more than it buys — name what a reader would follow with their eyes.

Default or custom animation

Cross-fade at a different duration    -> set animation-duration on ::view-transition-old/new(root)
Slide, scale, wipe                    -> keyframes on the old and new pseudo-elements
Direction-dependent motion            -> a transition type, selected with :active-view-transition-type()
Geometry computed at the moment of the transition (a reveal from a click point)
                                      -> await transition.ready, then animate the pseudo-element

Where the name is set

CSS is right for an element that is unique on the page — a header, a hero, a single panel. Script is right for anything appearing more than once, because a static rule over a list gives every row the same name and breaks the transition; assign per element before the transition and clear after it, or use `view-transition-name: match-element` where support allows.

</decision_fram

Read more
Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin

Other skills on agents-inc-skills.