View Transitions API en 2026: transiciones de página sin librerías
El salto seco al cambiar de página no es inevitable y tampoco hace falta cargar una librería de animación para evitarlo: con la View Transitions API el navegador toma las capturas del estado viejo y del nuevo y compone la transición. Esta es la guía práctica de lo que ya se puede usar hoy.
Durante años, animar el paso de una vista a otra significó elegir entre dos males: sumar una dependencia pesada (Framer Motion, GSAP, un plugin del router) o vivir con el parpadeo del navegador. La View Transitions API mueve ese trabajo al motor de renderizado, y eso cambia el cálculo incluso para un sitio multipágina servido con Blade.
Qué es la View Transitions API y qué problema resuelve
La idea es simple: cuando el DOM cambia, el navegador puede capturar una imagen del estado anterior y otra del nuevo, y animar entre ambas con CSS. No hay que calcular posiciones ni clonar nodos a mano.
El salto seco de toda la vida
En un sitio multipágina, cada clic destruye un documento y monta otro. El navegador pinta el nuevo sin ninguna relación visual con el anterior, y el resultado es ese corte brusco que el usuario interpreta como "la web cargó otra pantalla".
Lee también
El navegador captura, el CSS anima
Con la API activa, el navegador genera una capa de transición con pseudoelementos: ::view-transition-old() para la captura que se va y ::view-transition-new() para la que llega, agrupadas por ::view-transition-group(). El fundido cruzado es el comportamiento por defecto y se puede reemplazar por cualquier animación CSS.
Dos escenarios: misma página y páginas distintas
Conviene separarlos desde el principio, porque tienen soporte distinto y se activan de forma distinta. Las transiciones dentro de la misma página (cambio de pestañas, tema claro/oscuro, apertura de un panel) se disparan con document.startViewTransition(). Las transiciones entre páginas de un sitio multipágina se activan con una regla CSS y no necesitan JavaScript.
Estado del soporte en septiembre de 2026
Transiciones dentro de una misma página: Baseline desde octubre de 2025
La versión de nivel 1 de la API es Baseline Newly Available desde el 14 de octubre de 2025, cuando Firefox 144 completó el soporte. En la práctica: Chrome y Edge desde la 111, Safari desde la 18 y Firefox desde la 133, con el conjunto completo de funciones a partir de la 144. El paso a "ampliamente disponible" está proyectado para más adelante, en 2028.
Transiciones entre páginas: Chromium y WebKit delante, Firefox todavía detrás
Las transiciones entre documentos funcionan en Chrome y Edge desde la 126, en Safari desde la 18.2 y en Samsung Internet desde la 27. Firefox no las ofrece de forma general todavía, así que conviene tratarlas como una mejora progresiva: si el navegador no las soporta, la navegación ocurre igual, sin animación.
Mejora progresiva: si no hay soporte, la navegación sigue funcionando
Este es el punto que tranquiliza a la hora de decidir: nada de lo que se escribe para la API es obligatorio. La regla CSS que activa las transiciones entre páginas se ignora en un motor sin soporte, y el código que llama a document.startViewTransition() se puede envolver en una comprobación de existencia.
Transiciones dentro de la misma página
El ejemplo mínimo: document.startViewTransition()
El caso más simple envuelve el cambio de DOM en una llamada al método. El navegador captura el estado actual, ejecuta la función y anima el resultado:
if (document.startViewTransition) {
document.startViewTransition(() => {
document.querySelector("#panel").classList.toggle("abierto");
});
} else {
document.querySelector("#panel").classList.toggle("abierto");
}Qué devuelve la promesa: ready, updateCallbackDone y finished
La llamada devuelve un objeto con tres promesas que sirven para coordinar el resto del código. updateCallbackDone se cumple cuando la función de actualización terminó. ready se cumple cuando las capturas están hechas y la animación está a punto de arrancar. finished llega cuando la transición acaba. Si la transición se cancela (por ejemplo, porque hay dos elementos con el mismo nombre en el momento de la captura), ready se rechaza y conviene tener un catch para no dejar el flujo a medias.
Personalizar la animación con ::view-transition-old y ::view-transition-new
Para reemplazar el fundido por defecto basta con animar los pseudoelementos. Este bloque acorta la duración y controla la dirección del cruce:
::view-transition-old(root) {
animation: 180ms ease-out both salida;
}
::view-transition-new(root) {
animation: 240ms ease-in both entrada;
}
@keyframes salida {
to { opacity: 0; }
}
@keyframes entrada {
from { opacity: 0; }
}Dar nombre a un elemento para que viaje: view-transition-name
El detalle que convierte una transición correcta en una transición memorable es el elemento compartido. Cuando una miniatura y la imagen grande del detalle declaran el mismo view-transition-name, el navegador entiende que son el mismo objeto y lo mueve de una posición a otra en lugar de fundir dos pantallas. Un nombre debe ser único en cada momento de la captura: si se repite, la transición se cancela.
Agrupar estilos con view-transition-class y nombres automáticos
Repetir view-transition-name en veinte tarjetas de una cuadrícula es incómodo. La propiedad view-transition-class, del nivel 2 de la especificación, permite que varios elementos compartan estilos de transición sin compartir nombre, y la técnica habitual es generar nombres únicos desde un índice. La pseudoclase :active-view-transition permite aplicar estilos a la raíz solo mientras hay una transición en curso.
Transiciones entre páginas (sitios multipágina) sin JavaScript
La regla @view-transition { navigation: auto; } en las dos páginas
Para un sitio multipágina, todo el trabajo lo hace una regla CSS que debe estar en las dos páginas que participan (la de origen y la de destino), y ambas deben compartir el mismo origen:
@view-transition {
navigation: auto;
}Con eso, cada navegación por enlace entre esas páginas se anima con el fundido cruzado. No hay que tocar el enrutado, ni el HTML, ni el JavaScript del proyecto.
El truco del morph: el mismo view-transition-name en la lista y en el detalle
La regla general del párrafo anterior se puede afinar. Si la tarjeta del listado y la imagen del detalle comparten un nombre, el elemento viaja entre las dos páginas:
/* Página de listado */
.tarjeta-3 { view-transition-name: tarjeta-3; }
/* Página de detalle */
.imagen-destacada { view-transition-name: tarjeta-3; }El nombre tiene que ser el mismo en las dos páginas y único dentro de cada una. Es el patrón que da esa sensación de continuidad que antes solo se lograba con un router de SPA.
pageswap y pagereveal: retoques de último segundo
Dos eventos permiten ajustar cosas justo antes o después de la captura. pageswap se dispara en la página que se va, antes de tomar la captura, y sirve para asignar un nombre solo al elemento que realmente va a viajar. pagereveal se dispara en la página que llega y expone la transición en curso. En ambos casos el evento existe también cuando no hay soporte de transiciones, así que el código no se rompe.
Servidores con Blade, Astro o Turbo: dónde encaja cada pieza
Un sitio servido con plantillas de servidor es el escenario ideal: se añade la regla en la hoja de estilos del layout principal y queda cubierta toda la navegación entre rutas. No hay que convertir la web en una SPA ni hidratar nada. Si más adelante se quiere una transición dirigida, se combina con la Navigation API, que aporta la dirección de la navegación.
Cuándo la transición no se dispara (y parece que el código no funciona)
Mismo origen, recargas y bfcache
Las transiciones entre documentos solo se aplican a navegaciones del mismo origen. No hay transición al recargar la página, ni al volver atrás desde la caché de navegación (bfcache), ni cuando la cadena de redirecciones pasa por otro dominio. Además, si el documento está oculto (por ejemplo, la pestaña está en segundo plano), el navegador omite la transición por completo.
Nombres duplicados: la transición se cancela
Si dos elementos comparten el mismo view-transition-name en el instante de la captura, el navegador no puede decidir cuál animar y cancela la transición. Es un error fácil de cometer en listados largos y difícil de ver en pantalla, porque el resultado es simplemente que no hay animación.
Elementos fijos que saltan en la captura
Las barras de navegación y otros elementos con posición fija forman parte de la captura y pueden dar la impresión de saltar o quedarse pegados. La solución habitual es darles su propio nombre y animarlos aparte, o excluirlos del movimiento con una animación mínima.
Accesibilidad: movimiento reducido y foco
prefers-reduced-motion y cómo acortar la animación
Quien tiene configurado el sistema para reducir el movimiento no debería recibir una transición larga. Se acorta hasta hacerla prácticamente instantánea:
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation-duration: 0.01ms !important;
}
}No ocultar cambios de contexto detrás de una animación
Una transición es una pista visual, no un aviso. El cambio de página debe seguir ocurriendo de inmediato para el lector de pantalla y para el foco del teclado, y ninguna acción crítica debería depender de que el usuario vea la animación.
Un flujo completo: de la galería al detalle
Con las piezas anteriores se arma un patrón que funciona en producción sin dependencias. La regla @view-transition en las dos páginas anima la navegación, y el nombre compartido entre la miniatura de la galería y la imagen del detalle hace que el elemento viaje. Si el navegador no soporta las transiciones entre documentos, el enlace sigue navegando y el sitio se comporta como siempre.
Conclusión
La View Transitions API no reemplaza a una librería de animación en todos los casos, pero cubre bien el trabajo más común: cambios de estado, apertura de paneles y navegación entre páginas. La parte que ya es interoperable se puede adoptar hoy, y la que depende del motor se aplica como mejora progresiva sin riesgo.
Para seguir profundizando, el blog tiene una guía sobre animaciones CSS ligeras para mejorar la experiencia, un repaso de container queries y :has() y una guía de Tailwind CSS v4.3.

