transition:name y transition:animate: emparejar y animar
Las dos directivas que dan forma a una view transition. Cómo transition:animate elige la animación de un elemento entre fade, slide, initial y none; cómo transition:name asigna un nombre compartido que el navegador usa para emparejar un mismo elemento entre dos páginas y hacerlo morfar en lugar de desvanecerse; la regla de unicidad de los nombres, y cómo generar nombres estables en listas.
transition:animate: elegir la animación de un elemento
Por defecto, la transición de página es un fundido global. Con transition:animate reasignas la animación de un elemento concreto, y con ella la de su porción de la pantalla. Astro trae varias integradas. fade funde el elemento saliente con el entrante. slide lo desliza —hacia fuera por un lado y hacia dentro por el otro—, y es sensible a la dirección: en un salto hacia delante se desliza en un sentido y al pulsar atrás lo hace en el contrario, reforzando la sensación de ir y volver. initial deja la animación por defecto del navegador, y none la desactiva para ese elemento.
---// src/layouts/Base.astro---<header transition:animate="slide"> <slot name="titulo" /></header><main transition:animate="fade"> <slot /></main><footer transition:animate="none"> <slot name="pie" /></footer>Las animaciones aceptan además parámetros. En su forma de función puedes ajustar la duración o la curva de aceleración, escribiéndolo como una expresión de JavaScript en el atributo. Es útil para afinar el ritmo sin salir de las integradas.
---import { fade } from 'astro:transitions';---<article transition:animate={fade({ duration: '0.4s' })}> <slot /></article>transition:name: darle identidad a un elemento
transition:animate anima elementos en su sitio, pero no sabe que el título de la lista y el título del detalle son el mismo título. Para eso está transition:name: asigna a un elemento un nombre, que por debajo se traduce en la propiedad CSS view-transition-name. Cuando el navegador encuentra en la página vieja y en la nueva sendos elementos con el mismo nombre, no los funde por separado: entiende que uno es la continuación del otro y anima la transformación de su posición, tamaño y forma. El elemento morfa —viaja y se transforma— en lugar de aparecer y desaparecer.
Ese es el efecto que hace que una miniatura de una lista parezca despegarse y crecer hasta convertirse en la imagen de portada de la página de detalle. Basta con que ambos elementos, en sus páginas respectivas, compartan el mismo transition:name.
<!-- src/pages/blog/index.astro --><a href="/blog/astro-7"> <img src="/astro-7.jpg" transition:name="portada-astro-7" /> <h2 transition:name="titulo-astro-7">Astro 7 en 2026</h2></a><!-- src/pages/blog/astro-7.astro --><img src="/astro-7.jpg" transition:name="portada-astro-7" /><h1 transition:name="titulo-astro-7">Astro 7 en 2026</h1>En el salto entre esas dos páginas, la imagen y el título no se desvanecen: se desplazan y se redimensionan desde donde estaban en la lista hasta donde van en el detalle. El navegador hace el trabajo pesado de interpolar el movimiento; tú solo declaraste la identidad compartida.
La regla de unicidad, y por qué importa
Hay una restricción que no se puede quebrantar: en el instante de la transición, cada transition:name debe ser único dentro de cada página. Un nombre identifica un elemento, no una clase de elementos. Si dos elementos de la misma página comparten nombre, el navegador no sabe cuál emparejar y la transición se rompe o se ignora. Por eso los nombres literales fijos funcionan para elementos singulares —solo hay un encabezado, una portada, un pie— pero fallan en cuanto los repites.
El caso donde esto muerde es la lista. Si pintas veinte tarjetas y a todas les das transition:name="tarjeta", has violado la regla veinte veces. La solución es generar un nombre distinto para cada una a partir de un dato que ya las distingue: su identificador, su slug, su posición.
---// src/pages/blog/index.astroconst posts = await getCollection('blog');---<ul> {posts.map((post) => ( <li> <a href={`/blog/${post.id}`}> <img src={post.data.portada} transition:name={`portada-${post.id}`} /> <h2 transition:name={`titulo-${post.id}`}>{post.data.title}</h2> </a> </li> ))}</ul>En la página de detalle, ese mismo post.id reconstruye el nombre y cierra el emparejamiento, de modo que solo la tarjeta en la que hiciste clic morfa hacia la portada, y no las otras diecinueve.
---// src/pages/blog/[id].astroconst { post } = Astro.props;---<img src={post.data.portada} transition:name={`portada-${post.id}`} /><h1 transition:name={`titulo-${post.id}`}>{post.data.title}</h1>Componer un vocabulario de transiciones
Con estas dos directivas ya tienes un lenguaje completo. La estrategia que mejor escala no es animarlo todo, sino elegir los pocos elementos que dan continuidad visual entre dos vistas —la imagen que se agranda, el título que se mantiene, la cabecera que persiste— nombrarlos para que morfen, y dejar que el resto del contenido se funda con la transición por defecto. Menos nombres bien puestos comunican más que muchos nombres compitiendo. Un exceso de elementos morfando a la vez produce ruido; un puñado escogido produce la ilusión de que las dos páginas son dos estados de una misma superficie.