Descubre cómo la API de Portals propuesta puede mejorar la UX de navegación.
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 la plataforma web llamada Portales tiene como objetivo ayudar con esto, ya que optimiza la experiencia a medida que los usuarios navegan por tu sitio.
Mira cómo funcionan los portales:
Qué habilitan los portales
Las aplicaciones de una sola página (SPA) ofrecen transiciones atractivas, pero su compilación es más compleja. 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: primero, consulta lo que mostramos en 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 se habiliten los portales, confirma en DevTools que tienes el nuevo HTMLPortalElement
brillante.
Implementa portales
Veamos un ejemplo de implementación básica.
// 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.
Si quieres compilar algo como lo que mostramos en Chrome Dev Summit que funcione como la demostración anterior, el siguiente fragmento te resultará interesante.
// 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.
- Ingresa una URL de la que deseas obtener una vista previa.
- La página se incorporará como un elemento
<portal>
. - Haz clic en la vista previa.
- La vista previa se activará después de una animación.
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. Consiste en el atributosrc
, la funciónactivate
y una interfaz para el envío de mensajes (postMessage
).activate
toma un argumento opcional para pasar datos a<portal>
cuando se activa. - La interfaz
portalHost
: Agrega un objetoportalHost
al objetowindow
. 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 interesante llamadaadoptPredecessor
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);
});
Saber si 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 habilitar 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 entre orígenes, al igual que un <iframe>
. Por lo tanto, si tienes varios sitios web que se hacen referencia entre sí, también puedes usar los portales para crear una navegación fluida entre dos sitios web diferentes. Este caso de uso de varios orígenes es muy exclusivo de los portales y puede mejorar la experiencia del usuario de los 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.