List reorder transition
Animate list items to their new positions when order changes — toggle between normal and reversed.
Quick implementation
/* View Transitions: each item gets a unique name */
.list-item:nth-child(1) { view-transition-name: item-1; }
.list-item:nth-child(2) { view-transition-name: item-2; }
.list-item:nth-child(3) { view-transition-name: item-3; }
.list-item:nth-child(4) { view-transition-name: item-4; }
/* Customize the morph timing */
::view-transition-group(item-1),
::view-transition-group(item-2),
::view-transition-group(item-3),
::view-transition-group(item-4) {
animation-duration: 0.4s;
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
/* Trigger the transition in JS */
/* document.startViewTransition(() => reorderItems()); */
/* Pure CSS fallback: flex-direction swap */
.list {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.list.reversed {
flex-direction: column-reverse;
}
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*) {
animation-duration: 0.01s;
}
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building animated sortable lists.
Goal: When a list is reordered (sorted, filtered, reversed), animate each item from its old position to its new position.
Technical constraints:
- Assign a unique view-transition-name to each list item (e.g. item-1, item-2, …).
- Wrap the DOM reorder in document.startViewTransition() so the browser captures before/after snapshots.
- Set animation-duration on ::view-transition-group() for custom timing.
- Use oklch() for all color values — no hex or rgba().
- Use cubic-bezier(0.4, 0, 0.2, 1) for a material-style easing curve.
Framework variant (pick one):
A) Vanilla JS — reorder DOM nodes inside startViewTransition callback, CSS handles animation.
B) React — use startViewTransition in a state setter callback that changes the list order.
Edge cases to handle:
- Respect prefers-reduced-motion: set animation-duration to near-instant.
- Browsers without View Transitions: items snap to new positions — ensure layout still works.
- Dynamic lists: generate view-transition-name from item IDs, not indices, to handle additions/removals.
Return HTML + CSS + JS.
Why this matters in 2026
Animated list reordering previously required JavaScript FLIP libraries or framework-specific transition groups (React <TransitionGroup>, Vue <TransitionGroup>). The View Transitions API makes this a CSS concern: assign each item a view-transition-name, reorder the DOM inside startViewTransition(), and the browser animates each item from its old position to its new one automatically.
The logic
Each list item needs a unique view-transition-name — the browser uses this to match old and new positions. When you call document.startViewTransition(callback), the browser snapshots every named element, runs your callback (which reorders the DOM), then creates ::view-transition-group(name) pseudo-elements that interpolate between the old and new bounding boxes. The result is smooth positional animation without any JavaScript animation code.
Accessibility & performance
The browser performs the animation in compositor layers, so it's GPU-accelerated and doesn't block the main thread. For very long lists (100+ items), limit the number of named elements to the visible viewport to avoid excessive snapshots. Always respect prefers-reduced-motion by setting ::view-transition-group(*) animation-duration to near-zero. Announce the reorder to screen readers via an aria-live region.