View Transition API

Animaciones de transición entre páginas


Generalmente, cuando realizamos animaciones o transiciones, los elementos deben estar presentes en el DOM, es decir, tienen que existir en la página. Si pensamos en la animación o transición de una página a otra página, se trata de animar unos elementos del DOM de una página hasta unos elementos del DOM de otra página que aún no está cargada.

Si en un sitio web MPA (web orientada a contenido o SEO) pulsamos en un enlace, el navegador se mueve hacia otra página, volviendo a recargar toda la página y produciéndose una especie de parpadeo, que dependerá de la velocidad con la que cargue la nueva página, la conexión a Internet, etc. Ese parpadeo, generalmente es muy molesto y rompe con una navegación fluida.

Sin embargo, meter animaciones en este proceso es complejo, porque básicamente queremos animar con información que aún no tenemos disponible (y cuando la tengamos, hemos abandonado la anterior). Aquí es donde entra un nuevo estándar llamado View Transitions, que lo soluciona de una forma muy original.

¿Qué son las View Transition?

El nombre de View Transition viene de «transiciones de vistas», es decir, transiciones entre páginas de navegación, ya que a estas páginas muchas veces se les suele denominar Vistas (views).

¿En qué se basan las View Transition API? En unos conceptos muy sencillos:

  • 📸 Cuando se navega entre páginas, el navegador hace una «foto» de la página antes de abandonarla.
  • 🙈 El navegador carga la nueva página de forma transparente al usuario (mantiene la foto anterior)
  • 📸 Cuando la nueva página ha cargado, hace una nueva «foto» de la página de destino
  • ☄️ Aplica la animación o transición CSS de una «foto» a otra.

Estas «fotos» se crean mediante pseudoelementos CSS, que son una forma de CSS de crear «contenido virtual», es decir, que no existe realmente en el documento HTML.

En la actualidad, esta característica está en fase , por lo que si quieres utilizarla necesitarás revisar el soporte y activar la opción View Transition on navigation (en el caso de Chrome), por lo que tendrás que abrir una pestaña con la URL chrome://flags/#view-transition-on-navigation para activarla.

Ahora mismo, la compatibilidad de esta característica es muy reciente, por lo que sólo algunos navegadores disponen de esta feature. Se está implementando no sólo para aplicaciones SPA (Vue, React, etc...), sino también para webs MPA (Astro, Next, Nuxt, u otras más tradicionales donde el enfoque está en el contenido y en el SEO). Poco a poco irá ampliándose su soporte:

Cómo usar View Transitions

Vamos a analizar la forma más sencilla de crear View Transition. En primer lugar, necesitaremos añadir la siguiente etiqueta HTML en la cabecera de la página, es decir, en el interior de la etiqueta <head> del HTML.

La etiqueta <meta> indicará al navegador que se van a activar las View Transition y con el valor same-origin se indica que se van a realizar en el mismo dominio:

<head>
  <meta name="view-transition" content="same-origin">
</head>

La idea de esta especificación es que en el futuro se puedan hacer animaciones cross-origin, es decir, entre dominios diferentes. Sin embargo, de momento sólo se soportan en el mismo dominio.

Crear la animación entre vistas

Una vez hecho esto, ya tendremos unas transiciones suaves por defecto, pero serán muy genéricas, por lo que no serán muy vistosas. Lo que haremos será utilizar la propiedad CSS view-transition-name mediante la cuál le vamos a dar un nombre al elemento que queremos personalizar su animación:

Propiedad Valor Descripción
view-transition-name none | Le damos un nombre al elemento, para utilizarlo posteriormente en los pseudoelementos.

Así pues, por ejemplo, podríamos elegir el elemento con clase .container que es el que tiene todo el contenido de texto de la página, para animarlo posteriormente. En este caso, le daremos el nombre de page (podría ser cualquier otro nombre):

.container {
  view-transition-name: page;
}

Animación inicial y final

Ahora, vamos a utilizar los pseudoelementos que hacen referencia a las «fotos» de las que hablabamos antes. Por un lado, el pseudoelemento ::view-transition-old() hace referencia a la «foto» del DOM de la página anterior a pulsar en el enlace y navegar, y el pseudoelemento ::view-transition-new() hace referencia a la «foto» del DOM de la página nueva a la que hemos navegado:

Pseudoelementos Descripción
::view-transition-old() Inicio de la transición. Hace referencia al DOM de la página antigua.
::view-transition-new() Final de la transición. Hace referencia al DOM de la página nueva.

A continuación, colocamos una animación tanto en la transición de inicio como en la transición de final. El código que escribiríamos sería el siguiente (indicamos el nombre page entre paréntesis):

::view-transition-old(page) {
  animation: fade 0.2s linear forwards;
}

::view-transition-new(page) {
  animation: fade 0.3s linear reverse;
}

Observa que en el primer caso, ::view-transition-old() realizamos la animación fade durante 0.2s a un ritmo constante linear y una vez termine se queda en el último frame.

Si no sabes crear animaciones de CSS, en el siguiente artículo te explico como funcionan y como puedes crear una de forma muy sencilla: Animaciones con CSS.

Entonces la animación continuará con la de final, ::view-transition-new() y realizará la misma animación fade, pero durante 0.3s y al revés, de esta forma nos ahorramos tener que crear dos animaciones diferentes.

Por ejemplo, si la animación fade es la siguiente, la animación de inicio (old) ocultará el contenido del elemento .container (baja el opacity hasta cero), y mientras lo hace, hará que descienda 50px hacia abajo. Al terminar, continuará la animación de final (new), que realizará la animación al revés, es decir, aparecerá desde totalmente invisible y desplazada 50px hacia abajo, subirá 50px hasta volverse opaca del todo:

@keyframes fade {
  0% {
    opacity: 1;
    transform: translateY(0);
  }

  100% {
    opacity: 0;
    transform: translateY(50px);
  }
}

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev