Experiencia práctica con portales: navegación sin interrupciones en la Web

Descubre cómo la API de Portals propuesta puede mejorar la UX de navegación.

Yusuke Utsunomiya
Yusuke Utsunomiya

Asegurarte de que tus páginas se carguen rápido es clave para ofrecer una buena experiencia del usuario. Sin embargo, un área que a menudo pasamos por alto son las transiciones de página, lo que nuestros usuarios ven cuando se mueven entre páginas.

Una nueva propuesta de API de plataforma web llamada Portals tiene como objetivo ayudar con esto optimizando la experiencia a medida que los usuarios navegan por tu sitio.

Mira cómo funcionan los portales:

Integración y navegación sin inconvenientes con los portales. Creado por Adam Argyle.

Qué habilitan los portales

Las aplicaciones de una sola página (SPA) ofrecen transiciones agradables, pero su compilación tiene un costo mayor. Las aplicaciones de varias páginas (MPAs) son mucho más fáciles de compilar, pero terminas con pantallas en blanco entre las páginas.

Los portales ofrecen lo mejor de ambos mundos: la baja complejidad de un MPA con las transiciones fluidas de un SPA. Piensa en ellos como un <iframe>, ya que permiten la incorporación, pero, a diferencia de un <iframe>, también incluyen funciones para navegar a su contenido.

Ver para creer: te pedimos que primero eche un vistazo a lo que mostramos en la Chrome Dev Summit 2018:

Con las navegaciones clásicas, los usuarios deben esperar con una pantalla en blanco hasta que el navegador termine de renderizar el destino. Con los portales, los usuarios pueden experimentar una animación, mientras que <portal> renderiza previamente el contenido y crea una experiencia de navegación fluida.

Antes de los portales, podríamos haber renderizado otra página con un <iframe>. También podríamos haber agregado animaciones para mover el marco alrededor de la página. Sin embargo, un <iframe> no te permitirá navegar por su contenido. Los portales cierran esta brecha, lo que permite casos de uso interesantes.

Prueba los portales

Habilitación a través de about://flags

Para probar los portales en Chrome 85 y versiones posteriores, activa una marca experimental:

  • Habilita la marca about://flags/#enable-portals para las navegaciones del mismo origen.
  • Para probar las navegaciones entre orígenes, habilita también la marca about://flags/#enable-portals-cross-origin.

Durante esta fase inicial del experimento de Portales, también te recomendamos que uses un directorio de datos de usuario completamente independiente para tus pruebas. Para ello, configura la marca de línea de comandos --user-data-dir. Una vez que los portales estén habilitados, confirma en Herramientas para desarrolladores que tienes el nuevo HTMLPortalElement brillante.

Captura de pantalla de la consola de Herramientas para desarrolladores que muestra HTMLPortalElement

Implementa portales

Analicemos un ejemplo de implementación básico.

// Create a portal with the wikipedia page, and embed it
// (like an iframe). You can also use the <portal> tag instead.
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);

// When the user touches the preview (embedded portal):
// do fancy animation, e.g. expand …
// and finish by doing the actual transition.
// For the sake of simplicity, this snippet will navigate
// on the `onload` event of the Portals element.
portal.addEventListener('load', (evt) => {
   portal.activate();
});

Es así de sencillo. Prueba este código en la consola de DevTools. Se debería abrir la página de Wikipedia.

GIF de la demostración del estilo del portal de vista previa

Si quieres compilar algo como lo que mostramos en Chrome Dev Summit, que funcione como la demostración anterior, te interesará el siguiente fragmento.

// Adding some styles with transitions
const style = document.createElement('style');
style.innerHTML = `
  portal {
    position:fixed;
    width: 100%;
    height: 100%;
    opacity: 0;
    box-shadow: 0 0 20px 10px #999;
    transform: scale(0.4);
    transform-origin: bottom left;
    bottom: 20px;
    left: 20px;
    animation-name: fade-in;
    animation-duration: 1s;
    animation-delay: 2s;
    animation-fill-mode: forwards;
  }
  .portal-transition {
    transition: transform 0.4s;
  }
  @media (prefers-reduced-motion: reduce) {
    .portal-transition {
      transition: transform 0.001s;
    }
  }
  .portal-reveal {
    transform: scale(1.0) translateX(-20px) translateY(20px);
  }
  @keyframes fade-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }
`;
const portal = document.createElement('portal');
// Let's navigate into the WICG Portals spec page
portal.src = 'https://wicg.github.io/portals/';
// Add a class that defines the transition. Consider using
// `prefers-reduced-motion` media query to control the animation.
// https://developers.google.com/web/updates/2019/03/prefers-reduced-motion
portal.classList.add('portal-transition');
portal.addEventListener('click', (evt) => {
  // Animate the portal once user interacts
  portal.classList.add('portal-reveal');
});
portal.addEventListener('transitionend', (evt) => {
  if (evt.propertyName == 'transform') {
    // Activate the portal once the transition has completed
    portal.activate();
  }
});
document.body.append(style, portal);

También es fácil realizar la detección de atributos para mejorar progresivamente un sitio web con los portales.

if ('HTMLPortalElement' in window) {
  // If this is a platform that have Portals...
  const portal = document.createElement('portal');
  ...
}

Si quieres experimentar rápidamente cómo se sienten los Portales, prueba uskay-portals-demo.glitch.me. Asegúrate de acceder a ella con Chrome 85 o versiones posteriores y de activar la marca experimental.

  1. Ingresa una URL de la que deseas obtener una vista previa.
  2. La página se incorporará como un elemento <portal>.
  3. Haz clic en la vista previa.
  4. La vista previa se activará después de una animación.

Un GIF de la demostración de error del uso de portales

Consulta la especificación

Estamos analizando activamente la especificación de los portales en el grupo comunitario de incubación web (WICG). Para ponerte al día rápidamente, consulta algunas de las situaciones clave. Estas son las tres funciones importantes que debes conocer:

  • El elemento <portal>: Es el elemento HTML en sí. La API es muy simple. Consta del atributo src, la función activate y una interfaz de mensajería (postMessage). activate toma un argumento opcional para pasar datos a <portal> después de la activación.
  • Interfaz portalHost: Agrega un objeto portalHost al objeto window. Esto te permite comprobar si la página está incorporada como un elemento <portal>. También proporciona una interfaz para enviar mensajes (postMessage) al host.
  • La interfaz PortalActivateEvent: Es un evento que se activa cuando se activa <portal>. Hay una función ordenada llamada adoptPredecessor que puedes usar para recuperar la página anterior como un elemento <portal>. Esto te permite crear navegaciones fluidas y experiencias compuestas entre dos páginas.

Veamos más allá del patrón de uso básico. Esta es una lista no exhaustiva de lo que puedes lograr con los portales, junto con un código de muestra.

Personaliza el estilo cuando se incorpora como un elemento <portal>

// Detect whether this page is hosted in a portal
if (window.portalHost) {
  // Customize the UI when being embedded as a portal
}

Mensajes entre el elemento <portal> y portalHost

// Send message to the portal element
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);

// Receive message via window.portalHost
window.portalHost.addEventListener('message', (evt) => {
  const data = evt.data.someKey;
  // handle the event
});

Activa el elemento <portal> y recibe el evento portalactivate

// You can optionally add data to the argument of the activate function
portal.activate({data: {somekey: 'somevalue'}});

// The portal content will receive the portalactivate event
// when the activate happens
window.addEventListener('portalactivate', (evt) => {
  // Data available as evt.data
  const data = evt.data;
});

Cómo recuperar el predecesor

// Listen to the portalactivate event
window.addEventListener('portalactivate', (evt) => {
  // ... and creatively use the predecessor
  const portal = evt.adoptPredecessor();
  document.querySelector('someElm').appendChild(portal);
});

Cómo saber que tu página se adoptó como predecesora

// The activate function returns a Promise.
// When the promise resolves, it means that the portal has been activated.
// If this document was adopted by it, then window.portalHost will exist.
portal.activate().then(() => {
  // Check if this document was adopted into a portal element.
  if (window.portalHost) {
    // You can start communicating with the portal element
    // i.e. listen to messages
    window.portalHost.addEventListener('message', (evt) => {
      // handle the event
    });
  }
});

Si combinas todas las funciones que admiten los portales, puedes crear experiencias del usuario realmente atractivas. Por ejemplo, en la siguiente demostración, se muestra cómo los portales pueden permitir una experiencia del usuario fluida entre un sitio web y contenido incorporado de terceros.

Casos de uso y planes

Esperamos que hayas disfrutado de este breve recorrido por los portales. No vemos la hora de ver lo que crearás. Por ejemplo, te recomendamos que comiences a usar los portales para navegaciones no triviales, como la renderización previa de la página de tu producto más vendido desde una página de ficha de categoría de producto.

Otro aspecto importante que debes saber es que los portales se pueden usar en navegaciones de origen cruzado, al igual que un <iframe>. Por lo tanto, si tienes varios sitios web que se comparan entre sí, también puedes usar los portales para crear navegaciones fluidas entre dos sitios web diferentes. Este caso de uso de origen cruzado es muy exclusivo de los portales e incluso puede mejorar la experiencia del usuario de las SPA.

Recibimos comentarios

Los portales están listos para la experimentación en Chrome 85 y versiones posteriores. Los comentarios de la comunidad son fundamentales para el diseño de nuevas APIs, así que pruébalas y danos tu opinión. Si tienes solicitudes de funciones o comentarios, visita el repositorio de GitHub de WICG.