Saltearse al contenido

Tutorial - Ampliar con View Transitions

Las View transitions son una forma de controlar lo que sucede cuando los visitantes navegan entre páginas en tu sitio. La API de View Transitions de Astro te permite agregar funciones opcionales de navegación, como transiciones suaves entre páginas y animaciones, controlar la pila de historial del navegador de las páginas visitadas y evitar actualizaciones completas de la página para persistir algunos elementos y el estado de la página mientras se actualiza el contenido mostrado.

Prepárate para...

  • Importar y añadir el enrutador <ViewTransitions /> a un elemento head común
  • Agregar listeners de eventos durante el proceso de navegación para activar <script> según sea necesario
  • Añadir animaciones de transición de página utilizando directivas de transición
  • Excluir la navegación del lado del cliente para un enlace de página individual

Necesitarás un proyecto de Astro existente con una plantilla de base común o un componente <Head />.

Este tutorial utiliza el proyecto terminado del tutorial Crear un Blog para demostrar cómo agregar view transitions (navegación del lado del cliente) a un proyecto de Astro existente. Puedes hacer un fork y usar esa base de código localmente, o completar el tutorial en el navegador editando el código del tutorial del blog en StackBlitz.

En su lugar, puedes seguir estos pasos con tu propio proyecto de Astro, pero deberás ajustar las instrucciones para tu base de código.

Recomendamos utilizar nuestro proyecto de ejemplo para completar este breve tutorial primero. Luego, puedes aplicar lo que has aprendido para crear view transitions en tu propio proyecto.

En el tutorial introductorio Crear un Blog, aprendiste sobre la navegación incorporada basada en archivos de Astro: cualquier archivo .astro, .md o .mdx en cualquier lugar dentro de la carpeta src/pages/ se convertía automáticamente en una nueva página en tu sitio.

Para navegar entre estas páginas, utilizaste el elemento HTML estándar <a>. Por ejemplo, para crear un enlace a tu página “Acerca de”, agregaste <a href="/about/">Acerca de</a> en la cabecera de tu página. Cuando un visitante de tu sitio hacía clic en ese enlace, el navegador se actualizaba y cargaba una nueva página con contenido completamente nuevo.

Sección titulada Navegación de página completa vs. enrutamiento del lado del cliente (modo SPA)

Cuando un navegador se actualiza y carga una nueva página, no hay continuidad entre la página antigua y la nueva. Durante el enrutamiento del lado del cliente, se muestra una nueva página sin una actualización completa del navegador.

El enrutamiento del lado del cliente es una característica de los sitios de aplicaciones de una sola página (SPA), donde todo el sitio o aplicación es “una página” de JavaScript cuyo contenido se actualiza en función de la interacción del visitante.

Debido a que cada nueva página no requiere una actualización completa del navegador, el enrutamiento del lado del cliente te permite controlar las transiciones de página de varias maneras. Los elementos persistentes, como un encabezado común de la página, no tienen que ser completamente vuelto a renderizar en la pantalla. La transición de una página a otra puede parecer mucho más fluida. Además, el estado puede conservarse, ¡lo que te permite transferir valores de una página a la siguiente o incluso mantener un video reproduciéndose mientras tus visitantes navegan por las páginas!

Hay momentos en los que querrás o necesitarás una actualización completa del navegador. Por ejemplo, cuando un enlace lleva a un visitante a un documento .pdf, necesitarás que el navegador cargue esa nueva página desde el servidor. Incluso con las view transitions habilitadas en tu proyecto de Astro, podrás especificar cómo debería navegar el navegador tanto de forma predeterminada como de forma específica para cada enlace, incluso eligiendo no utilizar enrutamiento del lado del cliente en absoluto.

Lee más sobre las view transitions de Astro en nuestra guía, o sumérgete en las instrucciones a continuación para ampliar el blog con view transitions.

  1. Añadiendo view transitions a mi sitio de Astro…

  2. ¿Cuál no es un beneficio de las view transitions de Astro?

  3. El enrutador de las view transitions…

Ampliando el tutorial del blog con view transitions

Sección titulada Ampliando el tutorial del blog con view transitions

Los pasos a continuación te muestran cómo ampliar el producto final del tutorial “Crear un Blog” al agregar enrutamiento del lado del cliente para mejorar las view transitions.

  1. Actualiza a la última versión de Astro y todas las integraciones a sus versiones más recientes ejecutando los siguientes comandos en tu terminal:

    Ventana de terminal
    # Actualizar a Astro v4.x
    npm install astro@latest
    # Ejemplo: actualizar la integración de Preact en el tutorial del blog
    npm install @astrojs/preact@latest
  1. Importa y añade el componente <ViewTransitions /> al <head> de la plantilla de tu página.

    En el ejemplo del tutorial del blog, el elemento <head> se encuentra en src/layouts/BaseLayout.astro. Primero, el enrutador ViewTransitions debe importarse en el frontmatter del componente. Luego, agrega el componente de enrutamiento dentro del elemento <head>.

    src/layouts/BaseLayout.astro
    ---
    import { ViewTransitions } from "astro:transitions";
    import Header from "../components/Header.astro";
    import Footer from "../components/Footer.astro";
    import "../styles/global.css";
    const { pageTitle } = Astro.props;
    ---
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>{pageTitle}</title>
    <ViewTransitions />
    </head>
    <body>
    <Header />
    <h1>{pageTitle}</h1>
    <slot />
    <Footer />
    <script>
    import "../scripts/menu.js";
    </script>
    </body>
    </html>

    ¡No es necesaria ninguna otra configuración para habilitar la navegación predeterminada del lado del cliente de Astro! Astro creará animaciones de página predeterminadas basadas en las similitudes entre la página antigua y la nueva, y también proporcionará un comportamiento de respaldo para navegadores no compatibles.

  2. Navega entre páginas en la vista previa de tu sitio.

    Mira la vista previa de tu sitio en una pantalla grande, como en modo escritorio. Mientras te desplazas entre páginas en tu sitio, observa que el contenido de la página anterior parece desvanecerse a medida que el contenido de la nueva página se desvanece. Utiliza la guía de view transitions para agregar un comportamiento personalizado si no estás satisfecho con las configuraciones predeterminadas.

    Mira la vista previa de tu sitio en una pantalla más pequeña y trata de utilizar el menú desplegable para navegar entre páginas. Observa que el menú dejará de funcionar después de cargar la primera página.

Con las view transitions, algunos scripts pueden dejar de ejecutarse después de la navegación de página, a diferencia de lo que ocurre con las actualizaciones completas del navegador. Hay varios eventos durante la navegación del lado del cliente a los que puedes escuchar y disparar eventos cuando ocurren. Los scripts en tu proyecto necesitarán ahora engancharse a dos eventos para ejecutarse en el momento adecuado durante la navegación de la página: astro:page-load y astro:after-swap.

  1. Haz que el script que controla el componente del menú móvil <Hamburger /> esté disponible después de navegar a una nueva página.

    Para hacer que tu menú móvil sea interactivo después de navegar a una nueva página, agrega el siguiente código que escucha el evento astro:page-load, el cual se ejecuta al finalizar la navegación de la página, y en respuesta, ejecuta el script existente para que el menú desplegable funcione al hacer clic:

    src/scripts/menu.js
    document.addEventListener('astro:page-load', () => {
    document.querySelector('.hamburger').addEventListener('click', () => {
    document.querySelector('.nav-links').classList.toggle('expanded');
    });
    });
  2. Haz que el script que controla la alternancia de temas esté disponible después de la navegación de la página.

    El <script> que controla la alternancia de tema claro/oscuro se encuentra en el componente <ThemeIcon />. Para que la alternancia de tema siga funcionando en todas las páginas, elimina el atributo is:inline del script y agrega el mismo escuchador de eventos que en el ejemplo anterior, de modo que el evento astro:page-load pueda activar tu función existente.

    Actualiza la etiqueta de script existente para que tu función se ejecute en respuesta al evento astro:page-load, haciendo que la alternancia de tu tema sea interactiva después de que la nueva página esté completamente cargada y visible para el usuario.

    src/components/ThemeIcon.astro
    ---
    ---
    <button id="themeToggle"> /* ... */ </button>
    <style> /* ... */ </style>
    <script is:inline>
    document.addEventListener('astro:page-load', () => {
    const theme = (() => {
    if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
    return localStorage.getItem("theme");
    }
    if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
    return "dark";
    }
    return "light";
    })();
    if (theme === "light") {
    document.documentElement.classList.remove("dark");
    } else {
    document.documentElement.classList.add("dark");
    }
    window.localStorage.setItem("theme", theme);
    const handleToggleClick = () => {
    const element = document.documentElement;
    element.classList.toggle("dark");
    const isDark = element.classList.contains("dark");
    localStorage.setItem("theme", isDark ? "dark" : "light");
    };
    document
    .getElementById("themeToggle")
    .addEventListener("click", handleToggleClick);
    });
    </script>

    Ahora, el alternador de temas es interactivo en cada página al utilizar el enrutador <ViewTransitions />, después de que la página ha terminado de cargarse.

  3. Verifica el tema antes para evitar destellos en el modo oscuro.

    La alternancia de temas funciona en cada página, pero su script se carga al final del proceso de navegación, después de que la nueva página se ha cargado completamente en el navegador. Puede ocurrir un destello de la versión de tema claro del sitio antes de que se ejecute este script de alternancia de temas y verifique qué tema debe usar en la página.

    Para verificar y, si es necesario, establecer el modo oscuro más temprano en el proceso de navegación, crea una función que se ejecutará en respuesta al evento astro:after-swap. La siguiente función para verificar el tema oscuro en el localStorage del navegador se ejecutará inmediatamente después de que la nueva página haya reemplazado a la antigua, antes de que los elementos del DOM se pinten en la pantalla.

    Añade este nuevo script al componente <ThemeIcon />, además del script que controla la alternancia de temas.

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

Ahora, cada cambio de página que utilice el enrutador <ViewTransitions /> para la navegación del lado del cliente (y por lo tanto, tenga acceso al evento astro:after-swap) podrá detectar theme: dark desde el localStorage del navegador y actualizar la página actual en consecuencia antes de que se renderice para el espectador.

¿Cuál es el orden correcto de los eventos después de que un visitante hace clic en un enlace para ir a una nueva página durante la navegación del lado del cliente?

Personaliza las animaciones de transición

Sección titulada Personaliza las animaciones de transición
  1. Cambia la animación predeterminada de fade a slide para el título de la página.

    Con las view transitions habilitadas, actualmente tienes una pequeña transición de desvanecimiento configurada para todas las animaciones de transición de página. Astro también proporciona una animación incorporada llamada slide. Para cambiar el tipo de animación para un solo elemento, agrega la directiva transition:animate="".

    Por ejemplo, para hacer que los títulos de las páginas se deslicen en lugar de desvanecerse, agrega transition:animate="slide" al elemento <h1> en el BaseLayout:

    src/layouts/BaseLayout.astro
    ---
    import Header from "../components/Header.astro";
    import Footer from "../components/Footer.astro";
    import "../styles/global.css";
    import { ViewTransitions } from "astro:transitions";
    const { pageTitle } = Astro.props;
    ---
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>{pageTitle}</title>
    <ViewTransitions />
    </head>
    <body>
    <Header />
    <h1 transition:animate="slide">{pageTitle}</h1>
    <slot />
    <Footer />
    <script>
    import "../scripts/menu.js";
    </script>
    </body>
    </html>

En la vista previa de tu navegador, ahora verás que los títulos de las páginas se deslizan en la pantalla, mientras que otros elementos como el texto del cuerpo continúan desvaneciéndose.

Inténtalo tú mismo: Haz que los enlaces de navegación se deslicen.

Sección titulada Inténtalo tú mismo: Haz que los enlaces de navegación se deslicen.

Añade una directiva de animación para que el <div> en Navigation.astro, que contiene todos los enlaces del encabezado, se deslice al navegar por la página, siguiendo los mismos pasos mencionados anteriormente.

Muéstrame el código.
src/components/Navigation.astro
---
---
<div transition:animate="slide" class="nav-links">
<a href="/">Inicio</a>
<a href="/about/">Acerca de</a>
<a href="/blog/">Blog</a>
<a href="/tags/" >Etiquetas</a>
</div>

Verifica la vista previa de tu navegador y ahora tanto el título de la página como los enlaces del encabezado se deslizarán en cada navegación de página.

  1. Añade una transición de desvanecimiento más larga a las descripciones de tus publicaciones en el blog.

    También puedes personalizar las animaciones integradas en Astro importándolas y luego proporcionando cualquier propiedad de animación CSS.

    Por ejemplo, para hacer que la descripción aparezca lentamente cuando navegas a una entrada de blog, importa la animación fade en tu plantilla para las entradas de blog en formato Markdown. Luego, agrega la directiva de transición para el fade de Astro con una duración de 2s:

    src/layouts/MarkdownPostLayout.astro
    ---
    import BaseLayout from "./BaseLayout.astro";
    import { fade } from "astro:transitions";
    const { frontmatter } = Astro.props;
    ---
    <BaseLayout pageTitle={frontmatter.title}>
    <p>{frontmatter.pubDate.slice(0, 10)}</p>
    <p transition:animate={fade({ duration: '2s' })} ><em>{frontmatter.description}</em></p>
    <p>Escrito por: {frontmatter.author}</p>
    <img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
    <slot />
    </BaseLayout>

    Navega a cualquier entrada de blog en la vista previa de tu navegador y verás que la descripción aparece con una transición más lenta que el resto del texto.

    Lee más acerca de las diferentes directivas de transición y la personalización de animaciones.

Fuerza una recarga completa del navegador para algunos enlaces

Sección titulada Fuerza una recarga completa del navegador para algunos enlaces
  1. Evita el enrutamiento del lado del cliente y en su lugar exige al navegador que recargue cuando navegue a tu página Acerca de.

    En ocasiones, querrás que se realice una recarga completa del navegador cuando los visitantes hagan clic en ciertos enlaces. Por ejemplo, puede que estés vinculando a una página que no utiliza el enrutador <ViewTransitions />, o a un archivo directamente, como un archivo .pdf.

    Para lograr que tu navegador se actualice cada vez que hagas clic en el enlace de navegación para ir a tu página Acerca de, agrega el atributo data-astro-reload a la etiqueta <a> en tu componente <Navigation />. Esto anulará completamente el enrutador <ViewTransitions /> y cualquier animación de las view transitions para este enlace en particular.

    src/components/Navigation.astro
    ---
    ---
    <div transition:animate="slide" class="nav-links">
    <a href="/">Inicio</a>
    <a href="/about/" data-astro-reload >Acerca de</a>
    <a href="/blog/">Blog</a>
    <a href="/tags/">Etiquetas</a>
    </div>

    Ahora, cuando hagas clic en el enlace de navegación hacia tu página Acerca de, no se producirán animaciones. Los enlaces y el título de la página no se deslizarán y el contenido de la página no se desvanecerá al navegar a tu página Acerca de usando este enlace.

  2. Añade un enlace a tu página Acerca de desde tu nombre de autor en tu plantilla Markdown para las entradas del blog.

    data-astro-reload solo provoca una actualización completa del navegador al ir a una nueva página desde el enlace al que se ha añadido. No controla todas las instancias de navegación a tu página Acerca de.

    En tu compoente <MarkdownPostLayout />, agrega un enlace a tu página Acerca de en tu nombre de autor:

    src/layouts/MarkdownPostLayout.astro
    ---
    import BaseLayout from "./BaseLayout.astro";
    import { fade } from "astro:transitions";
    const { frontmatter } = Astro.props;
    ---
    <BaseLayout pageTitle={frontmatter.title}>
    <p>{frontmatter.pubDate.slice(0, 10)}</p>
    <p transition:animate={fade({ duration: '2s' })} ><em>{frontmatter.description}</em></p>
    <p>Escrito por: <a href="/about/">{frontmatter.author}</a></p>
    <img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
    <slot />
    </BaseLayout>

Si visitas cualquier entrada de blog en la vista previa del navegador y luego haces clic en el nombre del autor vinculado para ir a la página Acerca de, ¿cómo se ve la navegación de la página?

Cuando un visitante hace clic en un enlace a la página Acerca de desde una entrada de blog individual, el título de la página y los enlaces de navegación en la cabecera porque

¡Todavía hay mucho más por explorar! Consulta nuestra Guía completa de View Transitions para descubrir más cosas que puedes hacer con las view transitions.

Para ver el ejemplo completo del tutorial de blog que utiliza view transitions, visita la rama View Transitions en el repositorio del tutorial.