# View transitions in Astro: what persists and what reloads

The Astro router replaces the body on every navigation, so scripts run again. transition:persist and page-load fix most cases.

> Page: https://ui.eneawork.it/blog/astro-view-transitions
> Markdown: https://ui.eneawork.it/blog/astro-view-transitions.md

*2026-11-01*

Le view transitions in Astro si attivano con <ClientRouter /> nel layout: da quel momento ogni link interno viene intercettato, il body viene sostituito e il browser anima il cambio. Il costo è che nulla resta montato se non lo dichiari.

Il pacchetto astro ha 10.765.753 download settimanali nella settimana 23-29 ottobre 2026, letto da api.npmjs.org il 1 novembre 2026. Il catalogo EneUI misura 111.985 componenti, 1.556 blocchi, 12.808 icone da 1.472 librerie, letti da /api/stats il 1 novembre 2026. Ogni comando qui sotto gira in locale, senza account.

## Attivare il router

--- import { ClientRouter } from "astro:transitions"; ---

Fino ad Astro 4 il componente si chiamava ViewTransitions. Il nome nuovo dice cosa fa: non si limita all’API del browser, la sostituisce con un router lato client.

Misurato il 1 novembre 2026: in Astro 7.4.4 il router client pesa 25.553 byte in dist/transitions/router.js e 13.353 byte in swap-functions.js, in totale 38.906 byte prima della compressione. Metodo: metadati dei file letti da unpkg.com/astro/dist/transitions/?meta con una richiesta HTTP il 1 novembre 2026.

## Cosa sopravvive alla navigazione

## Un nome condiviso per l’animazione

--- const { posts } = Astro.props; --- {posts.map((post) => ( ))}

transition:name connette due elementi che rappresentano la stessa cosa in pagine diverse: il browser anima posizione e dimensione fra i due. Il nome deve essere unico sia nella pagina di partenza sia in quella di arrivo, quindi include l’id del post e non la parola cover.

Senza transition:name il router anima comunque il body intero con una dissolvenza: quella è l’animazione predefinita, e transition:animate la sostituisce quando serve un movimento diverso.

## Persistere un elemento

transition:persist conserva il nodo DOM quando l’elemento compare nella pagina nuova con la stessa identità. Di default un’isola persistita riceve le props nuove; transition:persist-props conserva quelle del primo render.

## Inizializzare dopo ogni navigazione

document.addEventListener("astro:page-load", () => { document.querySelectorAll("[data-reveal]").forEach((el) => { el.classList.add("is-visible"); }); });

Un listener su DOMContentLoaded gira una volta sola: dopo la prima navigazione non viene più chiamato. L’evento giusto è astro:page-load, che arriva anche al primo caricamento.

## Quando rompere l’intercettazione

## Il limite noto

Il router sostituisce il body, non lo stato JavaScript. Un contatore dentro un modulo ES riparte da zero a ogni navigazione, anche con transition:persist: la persistenza riguarda il DOM, non le variabili. Se lo stato deve vivere tra le pagine, mettilo in un archivio esplicito o in sessionStorage.

## La regola di decisione

Regola: aggiungi il router quando la navigazione è frequente e la testata resta identica fra le pagine; su un sito di tre pagine i 38,0 KB non si ripagano e il caricamento pieno è più prevedibile. Il secondo criterio è lo stato: se la pagina successiva deve ricordare quello che l’utente ha fatto, il router non basta.

Il costo si paga anche in debugging: un evento legato a window sopravvive alla navigazione, un listener su un nodo no, e la differenza si vede solo dopo il secondo click. Tieni un solo punto di inizializzazione e richiamalo da astro:page-load.

Il router emette quattro eventi oltre a astro:page-load: astro:before-preparation, astro:after-preparation, astro:before-swap e astro:after-swap. Servono a leggere l’URL in arrivo prima che il DOM cambi e a rimettere a posto un elemento dopo lo scambio, senza aspettare che la pagina nuova sia pronta.

## Comandi

npx astro check npx astro build

Dal catalogo: viewfinder flip carousel, il blocco logo Astro e saastro. Le guide: le content collections e la direttiva client mancante; il confronto: Astro contro Next.js sulla documentazione.

## FAQ

### Devo cambiare i miei link?

No. Il router intercetta i link interni che trova nel documento: basta che siano anchor normali con href.

### Perché lo script non parte più dopo la prima pagina?

Perché l’evento DOMContentLoaded non si ripete. Sposta l’inizializzazione su astro:page-load.

### Le view transitions funzionano su Safari e Firefox?

Sì, con gradi diversi di supporto dell’API del browser. Quando manca, Astro naviga normalmente senza animazione.

### Come disattivo le animazioni?

Rimuovi ClientRouter dal layout e torni alla navigazione classica. Per un solo link usa l’attributo data-astro-reload.

### Posso usarle con le isole React?

Sì. L’isola si smonta e si rimonta a ogni navigazione, a meno che tu non usi transition:persist sull’elemento che la contiene.
