view-transitions
View Transitions API
Guia para implementar view transitions en SPAs y MPAs, con soporte para React y Next.js.
Modelo Mental
La View Transitions API automatiza el patron FLIP (First, Last, Invert, Play) a nivel del browser. El browser captura screenshots del estado actual, vos actualizas el DOM, el browser captura el nuevo estado y anima entre ambos usando CSS Animations sobre pseudo-elementos generados.
Hay dos variantes que comparten los mismos building blocks:
| Variante | Trigger | Caso de uso |
|---|---|---|
| Same-document (SPA) | document.startViewTransition(callback) |
Cambios de estado en SPAs |
| Cross-document (MPA) | Navegacion + @view-transition CSS at-rule |
Navegacion entre paginas HTML |
Browser Support
- Same-document: Chrome 111+, Edge 111+, Safari 18+, Firefox 133+ — Baseline Newly Available
- Cross-document: Chrome 126+, Edge 126+, Safari 18.2+ — Firefox: en desarrollo
- view-transition-class: Chrome 125+, Safari 18.2+, Firefox 144+
- match-element: Chrome 137+, Safari 18.2+, Firefox 144+
Cross-document transitions es foco de Interop 2026. Siempre implementar con fallback graceful. Verificar soporte actual en caniuse.com.
Implementacion Rapida
Same-Document (SPA)
function navigateWithTransition(updateFn: () => void) {
// SIEMPRE feature detection
if (!document.startViewTransition) {
updateFn();
return;
}
document.startViewTransition(() => updateFn());
}
Cross-Document (MPA)
Agregar en el CSS global (ambas paginas, origen y destino):
/* Opt-in — reemplaza el meta tag obsoleto */
@view-transition {
navigation: auto;
}
Nombrar Elementos para Transicion
/* Mismo view-transition-name en ambos estados = shared element transition */
.thumbnail { view-transition-name: product-hero; }
.hero-image { view-transition-name: product-hero; }
Reglas Criticas
Seguir siempre estas reglas al implementar view transitions:
-
Feature detection obligatorio — Siempre chequear
document.startViewTransitionantes de usarlo. Sin esto, browsers sin soporte rompen. -
view-transition-name unico por snapshot — Dos elementos visibles con el mismo name abortan la transicion silenciosamente. Es el bug #1 mas comun.
-
prefers-reduced-motion — Siempre respetar. Agregar este CSS en todo proyecto:
@media (prefers-reduced-motion: reduce) { ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } } -
Duracion < 500ms — Sweet spot: 200-400ms. Transiciones largas mantienen snapshots en GPU memory.
-
Limitar elementos nombrados — Cada name crea un par old+new de snapshots rasterizados. 50 elementos = 100 imagenes en memoria. Ser selectivo.
-
Callback liviano — El browser espera que el callback de
startViewTransition()termine antes de capturar el nuevo estado. No meter heavy computation ahi. -
animation-fill-mode: forwards — Aplicar a animaciones custom para evitar flicker al terminar.
-
No usar el meta tag obsoleto —
<meta name="view-transition">es obsoleto. Usar@view-transition { navigation: auto; }. -
MPA: opt-in en AMBAS paginas — La at-rule debe estar en el CSS de la pagina origen Y la destino.
-
React: no usar flushSync — Un
flushSyncdurante una view transition fuerza a React a aplicar updates sincronicamente, lo cual skipea el flujo destartViewTransition.
Pseudo-elementos
Durante la transicion, el browser genera este arbol que se puede estilizar con CSS:
::view-transition
::view-transition-group(name)
::view-transition-image-pair(name)
::view-transition-old(name) → screenshot estado anterior
::view-transition-new(name) → vista live del nuevo estado
Customizar:
/* Duracion global */
::view-transition-group(*) { animation-duration: 0.4s; }
/* Desactivar crossfade root, solo animar named elements */
::view-transition-group(root) { animation: none; }
ViewTransition Object (SPA)
startViewTransition() retorna un objeto con tres promises:
| Promise | Se resuelve cuando... |
|---|---|
updateCallbackDone |
El callback del DOM termino |
ready |
Los pseudo-elementos estan creados, animacion por arrancar |
finished |
La animacion termino, nueva vista visible e interactiva |
Usar transition.ready para hijackear la animacion default con Web Animations API (ej: circular reveal).
View Transition Types (SPA)
Para condicionar animaciones CSS segun el tipo de navegacion:
document.startViewTransition({
update: () => updateDOM(),
types: ['slide-forward'],
});
:active-view-transition-type(slide-forward) {
&::view-transition-old(root) { animation: slide-to-left 0.3s; }
&::view-transition-new(root) { animation: slide-from-right 0.3s; }
}
Features Nuevas
match-element
Auto-naming para listas largas sin nombrar cada elemento:
.card {
view-transition-name: match-element;
view-transition-class: card;
}
view-transition-class
Agrupar multiples named elements bajo una misma animacion:
::view-transition-group(*.card) {
animation-duration: 0.3s;
}
Scoped View Transitions (experimental)
element.startViewTransition() en vez de document.startViewTransition(). Permite multiples transiciones simultaneas en distintos subtrees. No production-ready aun.
Integracion con React y Next.js
Para patrones detallados de integracion, leer references/react-nextjs.md.
Resumen rapido:
- React canary tiene
<ViewTransition>component nativo - Next.js tiene flag experimental
viewTransition: trueen next.config.js - next-view-transitions (Shu Ding) es la solucion pragmatica para App Router
- Para control imperativo, usar un hook wrapper sobre
startViewTransition()
Patrones de Animacion
Para patrones comunes (slide direction, product gallery morph, modal transitions), leer references/animation-patterns.md.
Debugging
- Chrome DevTools > Animations panel para scrubear transiciones
- Bajar velocidad al 10% para inspeccionar
- Pseudo-elementos visibles en Elements panel durante la transicion
Problemas comunes:
- Transicion no anima → Chequear names duplicados visibles
- Transicion se aborta → El callback throweo un error
- Overflow roto → Contenido en transicion rompe containment, usar CSS containment strategies
- React skipea transicion → Hay un
flushSyncen el medio
Checklist Pre-Deploy
[ ] Feature detection con fallback
[ ] prefers-reduced-motion implementado
[ ] Duracion < 500ms
[ ] view-transition-names unicos por estado
[ ] Elementos nombrados limitados (no 50+)
[ ] Callback liviano
[ ] animation-fill-mode: forwards en custom animations
[ ] MPA: @view-transition en AMBAS paginas + same-origin
[ ] Testeado en Chrome, Safari Y Firefox
[ ] No meta tag obsoleto
[ ] React: sin flushSync en transitions
More from testacode/llm-toolkit
claude-md-writer
Escribe y mejora archivos CLAUDE.md siguiendo best practices de Anthropic. Este skill se activa cuando el usuario dice "crear CLAUDE.md", "mejorar CLAUDE.md", "actualizar CLAUDE.md", "revisar CLAUDE.md", "escribir instrucciones del proyecto", "create CLAUDE.md", "improve CLAUDE.md", "review CLAUDE.md", "write project instructions", "optimize docs for Claude", "auditar CLAUDE.md", "audit CLAUDE.md", "limpiar CLAUDE.md", "dead weight", o configura un nuevo repositorio.
53doc-writer
Este skill se usa para crear documentos tecnicos organizados en /docs (specs, planes de implementacion, ADRs, documentacion de referencia). Se activa cuando el usuario dice "crear documento", "escribir spec", "documentar esto", "creame una spec", "escribime documentacion", "hacer documentacion", "write a spec", "create documentation", "write an ADR", o quiere agregar documentacion tecnica al proyecto.
44llms-txt-generator
This skill generates llms.txt documentation optimized for AI/LLM consumption. It should be used when the user says "crear llms.txt", "generate llms.txt", "documentar para AI", "document for AI", "crear documentacion para LLMs", "generate docs for LLMs", "make repo readable for Claude", or wants to create structured machine-readable documentation following the llms.txt standard.
40doc-organizer
Este skill se usa cuando el usuario pide "organizar docs", "ordenar documentacion", "mover documentos a carpetas", "categorizar archivos md", "reorganizar documentacion", o cuando hay archivos .md sueltos en docs/ que necesitan ser movidos a subcarpetas tematicas. Organiza y categoriza documentos tecnicos en la estructura correcta del proyecto.
28feature-planner
Planifica features con entrevista estructurada y crea tareas. Este skill se activa cuando el usuario dice "quiero agregar", "planificar feature", "nueva funcionalidad", "implementar esto", "crear plan", "planificar antes de codear", "disenar feature", "como deberia implementar esto", "pensar la arquitectura", o quiere alinear antes de escribir codigo.
27nextjs-project-starter
Creates Next.js projects with a configurable stack (Mantine, Supabase, Zustand, Zod). This skill should be used when the user says "create a Next.js project", "new web project", "bootstrap fullstack app", "start new app", "crear proyecto Next.js", "nuevo proyecto web", "empezar app fullstack", or wants to scaffold a new personal project from scratch.
25