Aprendiendo Portals: navegación perfecta en la web

Descubre cómo la propuesta de la API de Portals puede mejorar tu experiencia de usuario en la navegación.

Yusuke Utsunomiya
Yusuke Utsunomiya

Asegurarse de que tus páginas se carguen rápidamente es clave para ofrecer una buena experiencia de usuario. Pero un área que a menudo pasamos por alto son las transiciones de página: lo que ven nuestros usuarios cuando se mueven de una página a otra.

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

Mira a Portals en acción:

Incrustaciones y navegación sin problemas con Portals. Creado por Adam Argyle.

Qué habilita Portals

Las aplicaciones de página única (SPA) ofrecen buenas transiciones, pero tienen el costo de una mayor complejidad de construcción. Las aplicaciones de varias páginas (MPA) son mucho más fáciles de crear, pero terminas con pantallas en blanco entre las páginas.

Portals ofrece lo mejor de ambos mundos: la baja complejidad de un MPA con las transiciones fluidas de un SPA. Piensa en ellos como un <iframe> en el sentido de que permiten la incrustación, pero a diferencia de un <iframe>, también vienen con funciones para navegar a tu contenido.

Ver para creer: primero comprueba lo que mostramos en Chrome Dev Summit 2018:

Con las navegaciones clásicas, los usuarios tienen que esperar en una pantalla en blanco hasta que el navegador termine de renderizar el destino. Con Portals, los usuarios pueden experimentar una animación, mientras que el <portal> pre-renderiza el contenido y crea una experiencia de navegación perfecta.

Antes de Portals, podríamos haber renderizado otra página usando un <iframe>. También podríamos haber agregado animaciones para mover el marco por la página. Pero un <iframe> no te permitirá navegar por tu contenido. Los Portals cierran esta brecha, permitiendo casos de uso interesantes.

Prueba Portals

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

Prueba Portals en Chrome 85 y versiones posteriores habilitando una bandera experimental:

  • Habilita la bandera de about://flags/#enable-portals para navegaciones del mismo origen.
  • Para probar navegaciones de origen cruzado, también habilita la bandera de about://flags/#enable-portals-cross-origin.

Durante esta fase inicial del experimento de Portals, también recomendamos usar un directorio de datos de usuario completamente separado para tus pruebas configurando la bandera de línea de comando --user-data-dir. Una vez que Portals esté habilitado, confirma en DevTools que tienes el nuevo HTMLPortalElement.

Una captura de pantalla de la consola de DevTools que muestra HTMLPortalElement

Implementar Portals

Veamos un ejemplo básico de implementación.

// Crea un portal con la página de Wikipedia, e incrustala
// (en un iframe).También puedes usar la etiqueta de <portal>.
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);

// Cuando el usuario toca la vista preview (el portal incrusta // do):
// haz una animación llamativa, por ejemplo: expandir...
// y termina haciendo la actual transición.
// Por motivos de simplicidad, este código navegará
// en el evento de 'onload' del elemento de Portals
portal.addEventListener('load', (evt) => {
   portal.activate();
});

Es así de simple. Prueba este código en la consola de DevTools, la página de Wikipedia debería abrirse.

Un gif de demostración de estilo de un portal de vista previa

Si deseas crear algo como lo mostramos en Chrome Dev Summit y que funcione igual que la demostración anterior, el siguiente fragmento será de tu interés.

// Agregando algunos estilos con transiciones
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');
// Vamos a navegar a la página de especificaciones de WICG
//Portals
portal.src = 'https://wicg.github.io/portals/';
// Agrega una clase que defina la transición. Considera usar
// `prefers-reduced-motion` como consulta de medios para contr// olar la animación.
// https://developers.google.com/web/updates/2019/03/prefers-reduced-motion
portal.classList.add('portal-transition');
portal.addEventListener('click', (evt) => {
  // Lanzar la animación cuando el usuario interactué con
  // los Portals
  portal.classList.add('portal-reveal');
});
portal.addEventListener('transitionend', (evt) => {
  if (evt.propertyName == 'transform') {
    // Activar el Portal cuando la transición sea completada
    portal.activate();
  }
});
document.body.append(style, portal);

También es fácil realizar la detección de funciones para mejorar progresivamente un sitio web utilizando Portals.

if ('HTMLPortalElement' in window) {
  // Si esta es una plataforma que tiene Portals...
  const portal = document.createElement('portal');
  ...
}

Si deseas experimentar rápidamente cómo se siente Portals, intenta usar uskay-portals-demo.glitch.me. ¡Asegúrate de acceder a él con Chrome 85 o versiones posteriores y activa la bandera experimental!

  1. Ingresa una URL de la que desees obtener una vista previa.
  2. Luego, la página se incrustará 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 en Glitch usando Portals

Echa un vistazo a la especificación

Estamos discutiendo activamente la especificación de Portals en el Grupo de la Comunidad de Incubación Web (WICG). Para ponerte al día rápidamente, échale un vistazo a algunos de los escenarios clave. Estas son las tres características importantes con las que debes de familiarizarte:

  • El elemento <portal>: El propio elemento HTML. La API es muy sencilla. Consiste en el atributo desrc, la función de activate y una interfaz para mensajería (postMessage). activate toma un argumento opcional para pasar datos al <portal> al momento de la activación.
  • La interfaz portalHost: Agrega un objeto portalHost al objeto window. Esto te permite verificar si la página está incrustada como un elemento <portal>. También proporciona una interfaz para enviar mensajes (postMessage) de regreso al host.
  • La interfaz PortalActivateEvent: Un evento que se dispara cuando se activa <portal>. Hay una función llamada adoptPredecessor en la 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. Aquí hay una lista no exhaustiva de lo que puedes lograr con Portals junto con el código de muestra.

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

// Detecta si la página está en un host con Portals
if (window.portalHost) {
  // Personalizar la IU cuando se incrusta como un portal
}

Mensajería entre el elemento <portal> y portalHost

// Envía un mensaje al elemento de portal
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);

// Recibe un mensaje mediante window.portalHost
window.portalHost.addEventListener('message', (evt) => {
  const data = evt.data.someKey;
  // Maneja el evento
});

Activando el elemento <portal> y recibiendo el evento portalactivate

// Opcionalmente puedes agregar datos al argumentos para activ// ar la función
portal.activate({data: {somekey: 'somevalue'}});

// El contenido del portal recibirá el evento de portalactivat//e cuando el evento suceda
window.addEventListener('portalactivate', (evt) => {
  // Los datos estarán disponibles como evt.data
  const data = evt.data;
});

Recuperando el predecesor

// Escucha al evento de portalactivate
window.addEventListener('portalactivate', (evt) => {
  // ...y de manera creativa utiliza el predecesor
  const portal = evt.adoptPredecessor();
  document.querySelector('someElm').appendChild(portal);
});

Saber que tu página fue adoptada como predecesora

// La función de activación regresa una promesa.
// Cuando esta se resuelve, significa que el portal ha sido ac  // tivado.
// Si este documento fue adoptado por eso, window.portalHost // existirá
portal.activate().then(() => {
  // Verifica si el documento fue adoptado en un elemento de p    // ortal.
  if (window.portalHost) {
    // Puedes iniciar la comunicación con el elemento portal
    // en otras palabras, oír los mensajes
    window.portalHost.addEventListener('message', (evt) => {
      // manejar el evento
    });
  }
});

Al combinar todas las funciones compatibles con Portals, puedes crear experiencias de usuario muy elegantes. Por ejemplo, la siguiente demostración explica cómo los Portals pueden permitir una experiencia de usuario perfecta entre un sitio web y el contenido incrustado de terceros.

Planes y casos de uso

¡Esperamos que te haya gustado este breve recorrido por Portals! No podemos esperar a ver qué se te ocurre. Por ejemplo, es posible que desees comenzar a usar Portals para navegaciones no triviales, como: renderizar previamente la página para tu producto más vendido desde una página de lista de categorías de productos.

Otra cosa importante que debe saber es que los Portals se pueden usar en navegaciones de origen cruzado, al igual que un <iframe>. Por lo tanto, si tienes varios sitios web que hacen referencia cruzada entre sí, también puedes usar Portals para crear una navegación fluida entre dos sitios web diferentes. Este caso de uso de origen cruzado es muy exclusivo de Portals e incluso puede mejorar la experiencia del usuario de los SPA.

Bienvenida la retroalimentación

Portals está listo para experimentar en Chrome 85 y versiones posteriores. Los comentarios de la comunidad son cruciales para el diseño de nuevas API, así que úsalo y coméntanos lo que piensas. Si tienes alguna solicitud de función o comentarios, ve al repositorio en GitHub de WICG.