Saltar al contenido

View transitions

Las view transitions son transiciones animadas entre diferentes vistas de un sitio web. Son una elección de diseño popular para preservar la continuidad visual mientras los visitantes se mueven entre estados o vistas de una aplicación.

El soporte de view transitions y enrutamiento del lado del cliente de Astro está impulsado por la View Transitions browser API y también incluye:

Diferencias entre las view transitions nativas del navegador y el <ClientRouter /> de Astro

Sección titulada “Diferencias entre las view transitions nativas del navegador y el <ClientRouter /> de Astro”

Las view transitions nativas del navegador, cross-document pueden usarse en Astro para animar la navegación entre documentos en una multi-page app (MPA), a menudo proporcionando la experiencia de enrutamiento del lado del cliente de las single-page applications. No alteran la funcionalidad central de una aplicación multi-página, ni afectan ningún script existente o añaden JavaScript adicional a la carga de tu página. Simplemente añaden animaciones.

Para funcionalidades mejoradas de enrutamiento del lado del cliente y view transitions aún no soportadas completamente por la View Transition API, Astro proporciona un componente integrado y ligero para habilitar el enrutamiento del lado del cliente y convertir tu multi-page app en una single-page app con animaciones suaves al navegar.

Esto viene con algunos beneficios, como estado compartido entre páginas y elementos persistentes, y algunos inconvenientes, como la necesidad de reinicializar manualmente scripts o estado después de la navegación.

Añadir el componente integrado <ClientRouter /> de Astro:

Sin embargo, a medida que las APIs del navegador y los estándares web evolucionan, usar el <ClientRouter /> de Astro para esta funcionalidad adicional será cada vez más innecesario. Recomendamos mantenerte al día con el estado actual de las APIs del navegador para que puedas decidir si aún necesitas el enrutamiento del lado del cliente de Astro para las funcionalidades específicas que usas.

Importa y añade el componente <ClientRouter /> a tu <head> común o componente de layout compartido. Astro creará animaciones de página por defecto basadas en las similitudes entre la página antigua y la nueva, y también proporcionará comportamiento de fallback para navegadores no soportados.

El siguiente ejemplo muestra cómo añadir las animaciones de navegación de página por defecto de Astro en todo el sitio, incluyendo la opción de control de fallback por defecto para navegadores no soportados, importando y añadiendo este componente a un componente de Astro <CommonHead />:

src/components/CommonHead.astro
---
import { ClientRouter } from "astro:transitions";
---
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content={description} />
<ClientRouter />

¡No se necesita ninguna otra configuración para habilitar la navegación del lado del cliente por defecto de Astro!

Usa directivas de transición o sobrescribe la navegación del lado del cliente por defecto en elementos individuales para un control más fino.

Astro asignará automáticamente a los elementos correspondientes encontrados tanto en la página antigua como en la nueva un view-transition-name compartido y único. Este par de elementos coincidentes se infiere tanto por el tipo de elemento como por su ubicación en el DOM.

Usa directivas transition:* opcionales en los elementos de página de tus componentes .astro para un control más fino sobre el comportamiento de la transición de página durante la navegación.

En algunos casos, puedes querer o necesitar identificar tú mismo los elementos de view transition correspondientes. Puedes especificar un nombre para un par de elementos usando la directiva transition:name.

src/pages/old-page.astro
<aside transition:name="hero">
src/pages/new-page.astro
<aside transition:name="hero">

Ten en cuenta que el valor transition:name proporcionado solo puede usarse una vez en cada página. Establece esto manualmente cuando Astro no pueda inferir un nombre apropiado por sí mismo, o para un control más fino sobre la coincidencia de elementos.

Añadido en: astro@2.10.0

Puedes persistir componentes y elementos HTML (en lugar de reemplazarlos) durante las navegaciones de página usando la directiva transition:persist.

Por ejemplo, el siguiente <video> continuará reproduciéndose mientras navegas a otra página que contiene el mismo elemento de video. Esto funciona tanto para navegación hacia adelante como hacia atrás.

src/components/Video.astro
<video controls muted autoplay transition:persist>
<source
src="https://ia804502.us.archive.org/33/items/GoldenGa1939_3/GoldenGa1939_3_512kb.mp4"
type="video/mp4"
/>
</video>

También puedes colocar la directiva en un Astro island (un componente de framework de UI con una directiva client:). Si ese componente existe en la siguiente página, el island de la página antigua con su estado actual continuará mostrándose, en lugar de reemplazarlo con el island de la nueva página.

En el siguiente ejemplo, el estado interno del contador del componente no se reiniciará al navegar hacia adelante y hacia atrás entre páginas que contienen el componente <Counter /> con el atributo transition:persist.

components/Header.astro
<Counter client:load transition:persist initialCount={5} />

También puedes identificar manualmente los elementos correspondientes si el island/elemento está en un componente diferente entre las dos páginas.

src/pages/old-page.astro
<video
controls
muted
autoplay
transition:name="media-player"
transition:persist
/>
src/pages/new-page.astro
<MyVideo
controls
muted
autoplay
transition:name="media-player"
transition:persist
/>

Como abreviatura conveniente, transition:persist puede alternativamente tomar un nombre de transición como valor.

src/pages/index.astro
<video controls muted autoplay transition:persist="media-player">

Añadido en: astro@4.5.0

Esto te permite controlar si las props de un island deben persistir o no durante la navegación.

Por defecto, cuando añades transition:persist a un island, el estado se retiene durante la navegación, pero tu componente se volverá a renderizar con nuevas props. Esto es útil, por ejemplo, cuando un componente recibe props específicas de página como el title de la página actual.

Puedes sobrescribir este comportamiento estableciendo transition:persist-props además de transition:persist. Añadir esta directiva mantendrá las props existentes de un island (no se re-renderizará con nuevos valores) además de mantener su estado existente.

Astro viene con algunas animaciones integradas para sobrescribir la transición fade por defecto. Añade la directiva transition:animate a elementos individuales para personalizar el comportamiento de transiciones específicas.

  • fade (por defecto): Una animación de crossfade con opiniones. El contenido antiguo se desvanece y el contenido nuevo aparece gradualmente.
  • initial: Excluye la animación de crossfade con opiniones de Astro y usa el estilo por defecto del navegador.
  • slide: Una animación donde el contenido antiguo se desliza hacia la izquierda y el contenido nuevo se desliza desde la derecha. En la navegación hacia atrás, las animaciones son las opuestas.
  • none: Deshabilita las animaciones por defecto del navegador. Usa en el elemento <html> de una página para deshabilitar el fade por defecto para cada elemento de la página.

Combina directivas para un control completo sobre la animación de tu página. Establece un valor por defecto de página en el elemento <html>, y sobrescribe en cualquier elemento individual como desees.

El ejemplo a continuación produce una animación de deslizamiento para el contenido del body mientras deshabilita la animación de fade por defecto del navegador para el resto de la página:

---
import CommonHead from "../components/CommonHead.astro";
---
<html transition:name="root" transition:animate="none">
<head>
<CommonHead />
</head>
<body>
<header>
...
</header>
<!-- Override your page default on a single element -->
<main transition:animate="slide">
...
</main>
</body>
</html>

Puedes personalizar todos los aspectos de una transición con cualquier propiedad de animación CSS.

Para personalizar una animación integrada, primero importa la animación desde astro:transitions, y luego pasa opciones de personalización.

El siguiente ejemplo personaliza la duración de la animación fade integrada:

---
import { fade } from "astro:transitions";
---
<header transition:animate={fade({ duration: "0.4s" })}>

También puedes definir tus propias animaciones para usar con transition:animate definiendo tanto el comportamiento hacia adelante como hacia atrás, así como las páginas nueva y antigua, de acuerdo con los siguientes tipos:

export interface TransitionAnimation {
name: string; // The name of the keyframe
delay?: number | string;
duration?: number | string;
easing?: string;
fillMode?: string;
direction?: string;
}
export interface TransitionAnimationPair {
old: TransitionAnimation | TransitionAnimation[];
new: TransitionAnimation | TransitionAnimation[];
}
export interface TransitionDirectionalAnimations {
forwards: TransitionAnimationPair;
backwards: TransitionAnimationPair;
}

El siguiente ejemplo muestra todas las propiedades necesarias para definir una animación personalizada bump dentro de una etiqueta <style is:global> en tu archivo de layout raíz:

src/layouts/Layout.astro
---
import { ClientRouter } from "astro:transitions";
---
<html lang="en">
<head>
<ClientRouter />
</head>
<body>
<slot />
</body>
</html>
<style is:global>
@keyframes bump {
0% {
opacity: 0;
transform: scale(1) translateX(200px);
}
50% {
opacity: 0.5;
transform: scale(1.1);
}
100% {
opacity: 1;
transform: scale(1) translateX(0);
}
}
</style>

El comportamiento de la animación debe definirse en el frontmatter de cada componente que use la animación:

src/pages/index.astro
---
const anim = {
old: {
name: "bump",
duration: "0.5s",
easing: "ease-in",
direction: "reverse",
},
new: {
name: "bump",
duration: "0.5s",
easing: "ease-in-out",
},
};
const customTransition = {
forwards: anim,
backwards: anim,
};
---
<header transition:animate={customTransition}> ... </header>

Tienes gran flexibilidad al definir animaciones personalizadas. Para lograr el resultado deseado, puedes considerar combinaciones inusuales como usar diferentes objetos para adelante y atrás, o proporcionar animaciones keyframe separadas para la página antigua y la nueva.

El router <ClientRouter /> maneja la navegación escuchando:

  • Clics en elementos <a>.
  • Eventos de navegación hacia atrás y hacia adelante.

Las siguientes opciones te permiten controlar adicionalmente cuándo ocurre la navegación dentro del router:

Hay algunos casos donde no puedes navegar vía enrutamiento del lado del cliente ya que ambas páginas involucradas deben usar el router <ClientRouter /> para prevenir una recarga de página completa. También puedes no querer enrutamiento del lado del cliente en cada cambio de navegación y preferir una navegación de página tradicional en rutas seleccionadas.

Puedes excluirte del enrutamiento del lado del cliente a nivel de enlace añadiendo el atributo data-astro-reload a cualquier etiqueta <a> o <form>. Este atributo sobrescribirá cualquier componente <ClientRouter /> existente y en su lugar disparará una recarga del navegador durante la navegación.

El siguiente ejemplo muestra cómo prevenir el enrutamiento del lado del cliente al navegar a un artículo solo desde la página principal. Esto aún te permite tener animación en elementos compartidos, como una imagen hero, al navegar a la misma página desde una página de listado de artículos:

src/pages/index.astro
<a href="/articles/emperor-penguins" data-astro-reload>
src/pages/articles.astro
<a href="/articles/emperor-penguins">

Los enlaces con el atributo data-astro-reload serán ignorados por el router y ocurrirá una navegación de página completa.

También puedes disparar la navegación del lado del cliente vía eventos que normalmente no son escuchados por el router <ClientRouter /> usando navigate(). Esta función del módulo astro:transitions/client puede usarse en scripts, y en componentes de framework que son hidratados con una directiva client.

El siguiente ejemplo muestra un componente de Astro que navega a un visitante a otra página que selecciona de un menú:

src/components/Form.astro
<script>
import { navigate } from "astro:transitions/client";
// Navigate to the selected option automatically.
document.querySelector("select").onchange = (event) => {
let href = event.target.value;
navigate(href);
};
</script>
<select>
<option value="/play">Play</option>
<option value="/blog">Blog</option>
<option value="/about">About</option>
<option value="/contact">Contact</option>
</select>
src/pages/index.astro
---
import Form from "../components/Form.astro";
import { ClientRouter } from "astro:transitions";
---
<html>
<head>
<ClientRouter />
</head>
<body>
<Form />
</body>
</html>

El siguiente ejemplo implementa lo mismo usando navigate() en un componente <Form /> de React:

src/components/Form.jsx
import { navigate } from "astro:transitions/client";
export default function Form() {
return (
<select onChange={(e) => navigate(e.target.value)}>
<option value="/play">Play</option>
<option value="/blog">Blog</option>
<option value="/about">About</option>
<option value="/contact">Contact</option>
</select>
);
}

El componente <Form /> puede entonces ser renderizado en una página de Astro que usa el router <ClientRouter />, con una directiva client:

src/pages/index.astro
---
import Form from "../components/Form.jsx";
import { ClientRouter } from "astro:transitions";
---
<html>
<head>
<ClientRouter />
</head>
<body>
<Form client:load />
</body>
</html>

Para navegación hacia atrás y hacia adelante a través del historial del navegador, puedes combinar navigate() con las funciones integradas history.back(), history.forward() y history.go() del navegador. Si se llama a navigate() durante el renderizado del lado del servidor de tu componente, no tiene ningún efecto.

Consulta la referencia de astro:transitions para más información sobre las opciones de navigate().

Reemplazar entradas en el historial del navegador

Sección titulada “Reemplazar entradas en el historial del navegador”

Normalmente, cada vez que navegas, se escribe una nueva entrada en el historial del navegador. Esto permite la navegación entre páginas usando los botones atrás y adelante del navegador.

El router <ClientRouter /> te permite sobrescribir entradas del historial añadiendo el atributo data-astro-history a cualquier etiqueta <a> individual.

El atributo data-astro-history puede establecerse a los mismos tres valores que la opción history de la función navigate():

  • "push": el router usará history.pushState para crear una nueva entrada en el historial del navegador.
  • "replace": el router usará history.replaceState para actualizar la URL sin añadir una nueva entrada a la navegación.
  • "auto" (por defecto): el router intentará history.pushState, pero si la URL no es una a la que se pueda transicionar, la URL actual permanecerá sin cambios en el historial del navegador.

El siguiente ejemplo navega a la página /main pero no añade una nueva entrada al historial de navegación. En su lugar, reutiliza la entrada actual en el historial (/confirmation) y la sobrescribe.

src/pages/confirmation.astro
<a href="/main" data-astro-history="replace">

Esto tiene el efecto de que si vas hacia atrás desde la página /main, el navegador no mostrará la página /confirmation, sino la página anterior a esta.

Añadido en: astro@4.0.0

El router <ClientRouter /> disparará transiciones in-page desde elementos <form>, soportando tanto peticiones GET como POST.

Por defecto, Astro envía los datos de tu formulario como multipart/form-data cuando tu method está establecido en POST. Si quieres coincidir con el comportamiento por defecto de los navegadores web, usa el atributo enctype para enviar tus datos codificados como application/x-www-form-urlencoded:

src/components/Form.astro
<form
action="/contact"
method="POST"
enctype="application/x-www-form-urlencoded"
>

Puedes excluirte de las transiciones del router en cualquier formulario individual usando el atributo data-astro-reload:

src/components/Form.astro
<form action="/contact" data-astro-reload>

La API navigate() no realiza sanitización de las URLs que se le pasan. Si estás usando entrada del usuario para determinar la URL a la que navegar, deberías validar la entrada antes de pasarla a navigate().

Por ejemplo, un parámetro de consulta ?redirect podría usarse para navegar fuera de tu sitio (?redirect=http://example.com) o para ejecutar código arbitrario (?redirect=javascript:alert('Evil code')) si el valor no se sanitiza antes de usarlo.

Una forma de implementar esto de manera segura es asegurar que solo un conjunto de rutas conocidas pueda ser destino de redirección:

src/pages/index.astro
<script>
import { navigate } from 'astro:transitions/client';
const params = new URLSearchParams(window.location.search);
const redirect = params.get('redirect');
const allowedPaths = ['/home', '/about', '/contact'];
if (allowedPaths.includes(redirect)) {
navigate(redirect);
}
</script>

El tipo exacto de sanitización que necesitas dependerá de tu sitio y lo que quieras permitir.

Considera habilitar la funcionalidad de Content Security Policy de Astro para ayudar a proteger contra riesgos de cross-site scripting (XSS) si usas entrada del usuario con la API navigate().

El router <ClientRouter /> funciona mejor en navegadores que soportan View Transitions (ej. navegadores Chromium), pero también incluye soporte de fallback por defecto para otros navegadores. Incluso si el navegador no soporta la View Transitions API, el router de cliente de Astro aún puede proporcionar navegación dentro del navegador usando una de las opciones de fallback.

Dependiendo del soporte del navegador, puedes necesitar establecer explícitamente las directivas de transición name o animate en los elementos que deseas animar para una experiencia comparable en todos los navegadores:

src/pages/about.astro
---
import Layout from "../layouts/LayoutUsingClientRouter.astro";
---
<title transition:animate="fade">About my site</title>

Puedes sobrescribir el soporte de fallback por defecto de Astro añadiendo una propiedad fallback en el componente <ClientRouter /> y estableciéndola en swap o none:

  • animate (por defecto, recomendado): Astro simulará view transitions usando atributos personalizados antes de actualizar el contenido de la página.
  • swap: Astro no intentará animar la página. En su lugar, la página antigua será reemplazada inmediatamente por la nueva.
  • none: Astro no hará ninguna transición de página animada. En su lugar, obtendrás navegación de página completa en navegadores no soportados.
---
import { ClientRouter } from "astro:transitions";
---
<title>My site</title>
<ClientRouter fallback="swap" />

Cuando se usa el router <ClientRouter />, ocurren los siguientes pasos para producir la navegación del lado del cliente de Astro:

  1. Un visitante de tu sitio dispara la navegación mediante cualquiera de las siguientes acciones:

    • Hacer clic en una etiqueta <a> que enlaza internamente a otra página de tu sitio.
    • Hacer clic en el botón atrás.
    • Hacer clic en el botón adelante.
  2. El router comienza a fetchear la siguiente página.

  3. El router añade el atributo data-astro-transition al elemento HTML con un valor de "forward" o "back" según corresponda.

  4. El router llama a document.startViewTransition. Esto dispara el proceso de view transition del propio navegador. Importantemente, el navegador toma una captura del estado actual de la página.

  5. Dentro del callback de startViewTransition, el router realiza un swap, que consiste en la siguiente secuencia de eventos:

    • El contenido del <head> se intercambia, manteniendo algunos elementos:

      • Los nodos DOM de hojas de estilo se mantienen si existen en la nueva página, para prevenir FOUC.
      • Los scripts se mantienen si existen en la nueva página.
      • Cualquier otro elemento del head con transition:persist se mantiene si hay un elemento correspondiente en la nueva página.
    • El <body> se reemplaza completamente con el body de la nueva página.

    • Los elementos marcados con transition:persist se mueven al nuevo DOM si existen en la nueva página.

    • La posición de scroll se restaura si es necesario.

    • El evento astro:after-swap se dispara en el document. Este es el final del proceso de swap.

  6. El router espera a que las nuevas hojas de estilo se carguen antes de resolver la transición.

  7. El router ejecuta cualquier script nuevo añadido a la página.

  8. El evento astro:page-load se dispara. Este es el final del proceso de navegación.

Cuando añades view transitions a un proyecto de Astro existente, algunos de tus scripts pueden dejar de re-ejecutarse después de la navegación de página como lo hacían con las recargas de página completa del navegador. Usa la siguiente información para asegurar que tus scripts se ejecuten como se espera.

Al navegar entre páginas con el componente <ClientRouter />, los scripts se ejecutan en orden secuencial para coincidir con el comportamiento del navegador.

Bundled module scripts, que son los scripts por defecto en Astro, solo se ejecutan una vez. Después de la ejecución inicial serán ignorados, incluso si el script existe en la nueva página después de una transición.

A diferencia de los bundled module scripts, los inline scripts tienen el potencial de ser re-ejecutados durante la visita de un usuario a un sitio si existen en una página que se visita múltiples veces. Los inline scripts también pueden re-ejecutarse cuando un visitante navega a una página sin el script, y luego vuelve a una con el script.

Con las view transitions, algunos scripts pueden dejar de re-ejecutarse después de la navegación de página como lo hacen con las recargas de página completa del navegador. Hay varios eventos durante el enrutamiento del lado del cliente que puedes escuchar, y disparar eventos cuando ocurren. Puedes envolver un script existente en un event listener para asegurar que se ejecute en el momento adecuado del ciclo de navegación.

El siguiente ejemplo envuelve un script para un menú móvil "hamburger" en un event listener para astro:page-load que se ejecuta al final de la navegación de página para hacer que el menú responda a los clics después de navegar a una nueva página:

src/scripts/menu.js
document.addEventListener("astro:page-load", () => {
document.querySelector(".hamburger").addEventListener("click", () => {
document.querySelector(".nav-links").classList.toggle("expanded");
});
});

El siguiente ejemplo muestra una función que se ejecuta en respuesta al evento astro:after-swap, que ocurre inmediatamente después de que la nueva página ha reemplazado la página antigua y antes de que los elementos DOM se pinten en la pantalla. Esto evita un flash de tema en modo claro después de la navegación de página verificando y, si es necesario, estableciendo el tema en modo oscuro antes de que la nueva página se renderice:

src/components/ThemeToggle.astro
<script is:inline>
function applyTheme() {
localStorage.theme === "dark"
? document.documentElement.classList.add("dark")
: document.documentElement.classList.remove("dark");
}
document.addEventListener("astro:after-swap", applyTheme);
applyTheme();
</script>

Añadido en: astro@4.5.0

Para forzar que los inline scripts se re-ejecuten después de cada transición, añade la propiedad data-astro-rerun. Añadir cualquier atributo a un script también añade implícitamente is:inline, por lo que esto solo está disponible para scripts que no están empaquetados y procesados por Astro.

<script is:inline data-astro-rerun>...</script>

Para asegurar que un script se ejecute cada vez que se carga una página durante la navegación del lado del cliente, debería ser ejecutado por un evento del lifecycle. Por ejemplo, los event listeners para DOMContentLoaded pueden ser reemplazados por el evento del lifecycle astro:page-load.

Si tienes código que establece un estado global en un inline script, este estado necesitará tener en cuenta que el script puede ejecutarse más de una vez. Verifica el estado global en tu etiqueta <script>, y ejecuta tu código condicionalmente cuando sea posible. Esto funciona porque window se preserva.

<script is:inline>
if (!window.SomeGlobal) {
window.SomeGlobal = {};
}
</script>

El router <ClientRouter /> dispara varios eventos en el document durante la navegación. Estos eventos proporcionan hooks en el lifecycle de la navegación, permitiéndote hacer cosas como mostrar indicadores de que una nueva página se está cargando, sobrescribir el comportamiento por defecto, y restaurar estado mientras la navegación se completa.

El proceso de navegación involucra una fase de preparación, cuando se carga el nuevo contenido; una fase de DOM swap, donde el contenido de la página antigua es reemplazado por el contenido de la nueva página; y una fase de finalización donde se ejecutan los scripts, se reporta la carga como completada y se realizan tareas de limpieza.

Los eventos del lifecycle de la View Transition API de Astro en orden son:

Aunque algunas acciones pueden dispararse durante cualquier evento, algunas tareas solo pueden realizarse durante un evento específico para mejores resultados, como mostrar un spinner de carga antes de la preparación o sobrescribir pares de animación antes de intercambiar el contenido.

Añadido en: astro@3.6.0

Un evento que se dispara al inicio de la fase de preparación, después de que la navegación ha comenzado (ej. después de que el usuario ha hecho clic en un enlace), pero antes de que el contenido se cargue.

Este evento se usa:

  • Para hacer algo antes de que la carga haya comenzado, como mostrar un spinner de carga.
  • Para alterar la carga, como cargar contenido que has definido en una plantilla en lugar de desde la URL externa.
  • Para cambiar la dirección de la navegación (que normalmente es forward o backward) para animación personalizada.

Aquí hay un ejemplo de uso del evento astro:before-preparation para cargar un spinner antes de que el contenido se cargue y detenerlo inmediatamente después de la carga. Ten en cuenta que usar el callback loader de esta manera permite la ejecución asíncrona de código.

<script is:inline>
document.addEventListener("astro:before-preparation", (event) => {
const originalLoader = event.loader;
event.loader = async function () {
const { startSpinner } = await import("./spinner.js");
const stop = startSpinner();
await originalLoader();
stop();
};
});
</script>

Añadido en: astro@3.6.0

Un evento que se dispara al final de la fase de preparación, después de que el contenido de la nueva página se ha cargado y parseado en un documento. Este evento ocurre antes de la fase de view transitions.

Este ejemplo usa el evento astro:before-preparation para iniciar un indicador de carga y el evento astro:after-preparation para detenerlo:

<script is:inline>
document.addEventListener("astro:before-preparation", () => {
document.querySelector("#loading").classList.add("show");
});
document.addEventListener("astro:after-preparation", () => {
document.querySelector("#loading").classList.remove("show");
});
</script>

Esta es una versión más simple de cargar un spinner que el ejemplo mostrado arriba: si todo el código del listener puede ejecutarse sincrónicamente, no hay necesidad de hook en el callback loader.

Añadido en: astro@3.6.0

Un evento que se dispara antes de que el nuevo documento (que se popula durante la fase de preparación) reemplace el documento actual. Este evento ocurre dentro de la view transition, donde el usuario aún está viendo una captura de la página antigua.

Este evento puede usarse para hacer cambios antes de que ocurra el swap. La propiedad newDocument en el evento representa el documento entrante. Aquí hay un ejemplo para asegurar que la preferencia de modo claro u oscuro del navegador en localStorage se transfiera a la nueva página:

<script>
document.addEventListener("astro:before-swap", (event) => {
event.newDocument.documentElement.dataset.theme =
localStorage.getItem("darkMode") ? "dark" : "light";
});
</script>

El evento astro:before-swap también puede usarse para cambiar la implementación del swap. La implementación de swap por defecto hace diff del contenido del head, mueve los elementos persistentes del documento antiguo al newDocument, y luego reemplaza el body completo con el body del nuevo documento.

En este punto del lifecycle, podrías elegir definir tu propia implementación de swap, por ejemplo para hacer diff de todo el contenido del documento existente (lo que algunos otros routers hacen):

<script is:inline>
document.addEventListener("astro:before-swap", (event) => {
event.swap = () => {
diff(document, event.newDocument);
};
});
</script>

Añadido en: astro@4.15.0

El objeto swapFunctions del módulo astro:transitions/client proporciona cinco funciones de utilidad que manejan tareas específicas relacionadas con el swap, incluyendo el manejo de atributos del documento, elementos de página, y ejecución de scripts. Estas funciones pueden usarse directamente para definir una implementación de swap personalizada.

El siguiente ejemplo demuestra cómo usar estas funciones para recrear la implementación de swap integrada de Astro:

<script>
import { swapFunctions } from "astro:transitions/client";
// substitutes `window.document` with `doc`
function mySwap(doc: Document) {
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = swapFunctions.saveFocus();
swapFunctions.swapBodyElement(doc.body, document.body);
restoreFocusFunction();
}
document.addEventListener("astro:before-swap", (event) => {
event.swap = () => mySwap(event.newDocument);
});
<script>

Las implementaciones de swap personalizadas pueden comenzar con esta plantilla y añadir o reemplazar pasos individuales con lógica personalizada según sea necesario.

Un evento que se dispara inmediatamente después de que la nueva página reemplaza la página antigua. Puedes escuchar este evento en el document y disparar acciones que ocurrirán antes de que los elementos DOM de la nueva página se rendericen y los scripts se ejecuten.

Este evento, cuando se escucha en la página saliente, es útil para transferir y restaurar cualquier estado en el DOM que necesite transferirse a la nueva página.

Este es el último punto en el lifecycle donde aún es seguro, por ejemplo, añadir un nombre de clase de modo oscuro (<html class="dark-mode">), aunque puedes querer hacerlo en un evento anterior.

El evento astro:after-swap ocurre inmediatamente después de que el historial del navegador se ha actualizado y la posición de scroll se ha establecido. Por lo tanto, un uso de este evento es sobrescribir la restauración de scroll por defecto para la navegación del historial. El siguiente ejemplo reinicia la posición de scroll horizontal y vertical a la esquina superior izquierda de la página para cada navegación.

document.addEventListener("astro:after-swap", () =>
window.scrollTo({ left: 0, top: 0, behavior: "instant" }),
);

Un evento que se dispara al final de la navegación de página, después de que la nueva página es visible para el usuario y los styles y scripts bloqueantes se han cargado. Puedes escuchar este evento en el document.

El componente <ClientRouter /> dispara este evento tanto en la navegación de página inicial para una página pre-renderizada como en cualquier navegación subsiguiente, ya sea hacia adelante o hacia atrás.

Puedes usar este evento para ejecutar código en cada navegación de página, por ejemplo para configurar event listeners que de otro modo se perderían durante la navegación.

<script>
document.addEventListener("astro:page-load", () => {
// This runs on first page load and after every navigation.
setupStuff(); // e.g. add event listeners
});
</script>

Habilitar el enrutamiento del lado del cliente y animar las transiciones de página conllevan desafíos de accesibilidad, y Astro busca hacer que los sitios que optan por View Transitions sean lo más accesibles por defecto posible.

Añadido en: astro@3.2.0

El componente <ClientRouter /> incluye un anunciador de ruta para la navegación de página durante el enrutamiento del lado del cliente. No se necesita configuración ni acción para habilitar esto.

Las tecnologías asistivas permiten a los visitantes saber que la página ha cambiado anunciando el nuevo título de página después de la navegación. Cuando se usa enrutamiento del lado del servidor con recargas de página completas tradicionales del navegador, esto ocurre por defecto después de que la nueva página se carga. En el enrutamiento del lado del cliente, el componente <ClientRouter /> realiza esta acción.

Para añadir el anuncio de ruta al enrutamiento del lado del cliente, el componente añade un elemento a la nueva página con el atributo aria-live establecido en assertive. Esto le dice a la AT (tecnología asistiva) que anuncie inmediatamente. El componente también verifica lo siguiente, en orden de prioridad, para determinar el texto del anuncio:

  • El <title>, si existe.
  • El primer <h1> que encuentre.
  • El pathname de la página.

Recomendamos encarecidamente que siempre incluyas un <title> en cada página para accesibilidad.

El componente <ClientRouter /> de Astro incluye una media query CSS que deshabilita todas las animaciones de view transition, incluyendo la animación de fallback, siempre que se detecta la configuración prefers-reduced-motion. En su lugar, el navegador simplemente intercambiará los elementos DOM sin una animación.

Contribuir Comunidad Patrocinar