Animated List Reorder with View Transitions
Animate list items smoothly to their new positions when the underlying data sorts, filters, or shuffles — replacing the React Spring/Framer Motion FLIP layer entirely.
Detailed Explanation
FLIP, But Free
Before the View Transitions API, animating list reorders required FLIP (First, Last, Invert, Play): you measured the old positions, mutated the DOM, measured the new positions, applied inverse transforms, then animated to identity. Libraries like Framer Motion's <AnimatePresence layout> automated this, but they pulled megabytes of JavaScript.
With View Transitions, every list item just needs a unique name:
.todo-item {
view-transition-name: var(--item-name);
}
{todos.map(t => (
<li key={t.id} style={{'--item-name': `todo-${t.id}`}}>{t.text}</li>
))}
function sortTodos() {
document.startViewTransition(() => {
setTodos([...todos].sort((a, b) => a.priority - b.priority));
});
}
The browser captures the position of every named item before the sort, captures again after React commits, and animates each one to its destination.
Adding entrance/exit animations
For items that are added or removed, the browser falls back to the default cross-fade. Override with:
::view-transition-new(.todo-item) {
animation: 250ms ease-out both fade-in-up;
}
Nested transitions
If a list lives inside a route that itself transitions, the outer route transition contains the inner item transitions. This nesting is handled automatically — you do not need to coordinate manually.
Edge case: long lists
For lists with 100+ items, naming all of them creates 100+ snapshot groups. Consider only naming the visible viewport items by toggling view-transition-name based on IntersectionObserver visibility.
Use Case
Todo apps with sortable lists, kanban boards reordering cards, leaderboards updating ranks, search results re-sorting, and any data table where row order changes meaningfully in response to user input.