View Transitions y Animaciones de Navegación
Laboratorio: navegación, animación y estado #
Compara dos páginas ficticias con una isla compartida. La animación visual y la conservación de estado son decisiones distintas: prueba ambas de forma independiente.
Laboratorio interactivo
Transiciones: animación y estado
Navega entre dos páginas ficticias con una animación real del navegador. Compara remonte de una isla y conservación de su estado. Es una demostración local del concepto transition:persist, sin router ni peticiones Astro.
Página 1 · Catálogo
Selecciona un curso para abrir su detalle.
Isla compartida · página 1
Contador persistente: 0
Navegaciones: 0. La isla se vuelve a montar en cada navegación; su estado se reinicia.
Cambiar la opción de persistencia reinicia el experimento del contador. Se respeta movimiento reducido; sin soporte de Web Animations la navegación funciona sin animación. En Astro real, persistir requiere un elemento correspondiente en ambas páginas. Este ejemplo muestra props actualizadas, sin modelar persist-props. Transiciones de Astro.
Experimenta: Suma dos veces y cambia de página: sin persistencia el contador vuelve a cero. Activa persistencia, vuelve a sumar y navega: cambia el contenido y se mantiene el contador. La animación por sí sola no conserva el estado.
Astro incluye soporte de primera clase para la API de View Transitions, permitiendo crear experiencias de usuario fluidas, dinámicas y con transiciones tipo Single Page Application (SPA) sin renunciar a la arquitectura Zero-JS basada en HTML estático.
1. ¿Qué son las View Transitions? #
Tradicionalmente, cuando un usuario hace clic en un enlace a otra página:
- La pantalla se vuelve blanca momentáneamente.
- El navegador descarga el nuevo HTML, CSS y JS desde cero.
- Se vuelve a renderizar toda la página, perdiendo el estado visual.
Con View Transitions, Astro intercepta la navegación del lado del cliente, solicita el HTML de la nueva página en segundo plano e interpola suavemente los elementos comunes mediante animaciones CSS de alto rendimiento.
2. Activación en el Layout con ClientRouter #
Para activar la navegación instantánea en todo el sitio, importa e inserta el componente <ClientRouter /> (llamado <ViewTransitions /> en versiones anteriores de Astro) dentro de la etiqueta <head> de tu layout principal:
📄 src/layouts/BaseLayout.astro
1--- 2import { ClientRouter } from 'astro:transitions'; 3const { title } = Astro.props; 4--- 5 6<html lang="es"> 7 <head> 8 <meta charset="UTF-8" /> 9 <title>{title}</title> 10 <ClientRouter /> 11 </head> 12 <body> 13 <slot /> 14 </body> 15</html>
✅ Con esta única línea, todas las etiquetas <a href="..."> del sitio navegarán de forma instantánea sin recarga brusca.
3. Animación de elementos compartidos (transition:name) #
El superpoder visual más impactante es conectar visualmente un elemento de la página origen con otro en la página destino mediante el atributo transition:name.
Ejemplo: Imagen de portada de un Blog #
En la lista de posts (/blog):
1--- 2// src/pages/blog/index.astro 3--- 4<a href={`/blog/${post.slug}`}> 5 <img 6 src={post.data.image} 7 alt={post.data.title} 8 transition:name={`hero-image-${post.slug}`} 9 class="w-48 h-32 rounded-lg" 10 /> 11 <h2 transition:name={`hero-title-${post.slug}`}>{post.data.title}</h2> 12</a>
En la vista de detalle (/blog/[slug]):
1--- 2// src/pages/blog/[slug].astro 3--- 4<article> 5 <img 6 src={post.data.image} 7 alt={post.data.title} 8 transition:name={`hero-image-${post.slug}`} 9 class="w-full h-80 rounded-2xl shadow-xl" 10 /> 11 <h1 transition:name={`hero-title-${post.slug}`}>{post.data.title}</h1> 12 <p>{post.body}</p> 13</article>
✨ Al hacer clic, la imagen y el título se expanden y flotan suavemente de su tamaño pequeño en la lista a su posición final en el artículo.
TIP
El valor detransition:namedebe ser único en la página actual para que el navegador sepa qué elementos emparejar.
4. Tipos de animación (transition:animate) #
Astro proporciona animaciones predefinidas que puedes aplicar a cualquier contenedor o elemento:
1<!-- Desvanecimiento suave --> 2<main transition:animate="fade"> 3 <slot /> 4</main> 5 6<!-- Deslizamiento lateral --> 7<div transition:animate="slide"> 8 <p>Contenido deslizable</p> 9</div> 10 11<!-- Sin animación (cambio instantáneo) --> 12<header transition:animate="none"> 13 <nav>...</nav> 14</header>
5. Persistencia de estado con transition:persist #
Si tienes elementos interactivos como un reproductor de música/audio, un vídeo o un buscador con texto introducido, puedes evitar que se destruyan o se reinicien al navegar entre páginas agregando transition:persist:
1--- 2// src/components/AudioPlayer.astro 3--- 4<aside transition:persist="mini-reproductor" class="fixed bottom-4 right-4 bg-black p-4 text-white rounded-xl"> 5 <p>Reproduciendo Podcast...</p> 6 <audio controls src="/audio/capitulo-1.mp3"></audio> 7</aside>
🎵 El audio seguirá reproduciéndose sin cortes aunque el usuario visite diferentes páginas del sitio.
6. Ciclo de vida y scripts con astro:page-load #
Cuando se usan View Transitions, el evento tradicional window.onload o DOMContentLoaded solo se ejecuta en la carga inicial. Para inicializar librerías (gráficos, modales, tooltips) en cada cambio de ruta, escucha el evento astro:page-load:
1<script> 2 document.addEventListener('astro:page-load', () => { 3 console.log('Nueva página cargada mediante View Transitions'); 4 // Inicializar tooltips o animaciones JS aquí 5 }); 6</script>
Resumen del tema
Conceptos clave #
- Enrutador de cliente (
<ClientRouter />): componente deastro:transitionsque intercepta navegación en enlaces internos y actualiza el DOM dinámicamente. - Morfismo de elementos (
transition:name): identificador compartido entre páginas para animar posición, escala y forma de un elemento continuo. - Persistencia en el DOM (
transition:persist): directiva que previene el desmontaje de componentes multimedia o formularios entre transiciones de ruta. - Animaciones integradas (
transition:animate): opcionesfade,slideynonepara transiciones de contenedores. - Evento
astro:page-load: disparador estándar del ciclo de vida para re-ejecutar código JavaScript tras cada cambio de página.
Qué debes recordar #
Añade <ClientRouter /> en tu layout base y usa transition:name para morphing de portadas y transition:persist para reproductores continuos sin perder rendimiento estático.