React
View transitions in Astro: cosa persiste e cosa si ricarica
Il router di Astro sostituisce il body a ogni navigazione, quindi gli script ripartono. transition:persist e page-load risolvono quasi tutti i casi.
In sintesi
- ClientRouter intercetta i link interni e sostituisce il body a ogni navigazione.
- transition:persist conserva il nodo DOM, non lo stato JavaScript.
- astro:page-load è l’evento da usare al posto di DOMContentLoaded.
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.
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.
Cosa sopravvive alla navigazione
| Elemento | Comportamento predefinito | Direttiva |
|---|---|---|
| Isola interattiva | Si smonta e si rimonta | Nessuna |
| Player audio | Si interrompe | transition:persist |
| Modale aperta | Si chiude | transition:persist |
| Script inline | Rieseguito a ogni pagina | astro:page-load |
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
- Link verso un’altra origine: nessuna intercettazione, navigazione normale.
- Download o PDF: aggiungi
data-astro-reloadper un caricamento pieno. - Form con POST: non passa dal router, la pagina si ricarica.
- Dare lo stesso
transition:namea due immagini della stessa pagina: l’animazione parte dall’elemento sbagliato.
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.
Domande frequenti
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.