Portali pratici: navigazione sul Web senza interruzioni

Scopri in che modo l'API Portals proposta può migliorare l'esperienza utente di navigazione.

Yusuke Utsunomiya
Yusuke Utsunomiya

Assicurarsi che le pagine vengano caricate rapidamente è fondamentale per offrire una buona esperienza utente. Tuttavia, un aspetto che spesso trascuriamo sono le transizioni tra le pagine, ovvero ciò che gli utenti vedono quando si spostano da una pagina all'altra.

Una nuova proposta di API per piattaforme web chiamata Portals ha lo scopo di contribuire a semplificare l'esperienza degli utenti mentre navigano nel tuo sito.

Guarda i portali in azione:

Embedding e navigazione fluidi con i portali. Creato da Adam Argyle.

Cosa abilitano i portali

Le applicazioni a pagina singola (SPA) offrono transizioni piacevoli, ma la loro creazione è più complessa. Le applicazioni multipagina (MPA) sono molto più facili da creare, ma alla fine hai schermate vuote tra le pagine.

I portali offrono il meglio di entrambi i mondi: la bassa complessità di un MPA con le transizioni senza interruzioni di un'SPA. Pensa a loro come a un <iframe> in quanto consentono l'embedding, ma, a differenza di un <iframe>, includono anche funzionalità per accedere ai loro contenuti.

I fatti parlano da soli: innanzitutto, dai un'occhiata a cosa abbiamo mostrato al Chrome Dev Summit 2018:

Con le navigazioni classiche, gli utenti devono attendere con una schermata vuota fino al termine del rendering della destinazione da parte del browser. Con i portali, gli utenti possono usufruire di un'animazione, mentre <portal> esegue il pre-rendering dei contenuti e crea un'esperienza di navigazione fluida.

Prima dei portali, avremmo potuto visualizzare un'altra pagina utilizzando un <iframe>. Avremmo anche potuto aggiungere animazioni per spostare il frame all'interno della pagina. Tuttavia, un <iframe> non ti consente di accedere ai contenuti. I portali colmano questa lacuna, consentendo casi d'uso interessanti.

Provare i portali

Attivazione tramite about://flags

Prova Portali in Chrome 85 e versioni successive attivando un flag sperimentale:

  • Attiva il flag about://flags/#enable-portals per le navigazioni con la stessa origine.
  • Per testare le navigazioni cross-origin, attiva anche il flag about://flags/#enable-portals-cross-origin.

Durante questa prima fase dell'esperimento sui portali, ti consigliamo inoltre di utilizzare una directory dei dati utente completamente separata per i test impostando il --user-data-dir flag della riga di comando. Una volta attivati i portali, verifica in DevTools che sia presente il nuovo HTMLPortalElement.

Uno screenshot della console DevTools che mostra HTMLPortalElement

Implementare i portali

Vediamo un esempio di implementazione di base.

// 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();
});

È semplicissimo. Prova questo codice nella console di DevTools. Dovresti aprire la pagina di Wikipedia.

Una GIF della demo dello stile del portale di anteprima

Se vuoi creare qualcosa di simile a quanto mostrato al Chrome Dev Summit e che funzioni come la demo qui sopra, lo snippet seguente potrebbe interessarti.

// 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);

È inoltre facile rilevare le funzionalità per migliorare progressivamente un sito web utilizzando i portali.

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

Se vuoi provare rapidamente l'esperienza di Portals, prova a utilizzare uskay-portals-demo.glitch.me. Assicurati di accedervi con Chrome 85 o versioni successive e di attivare il flag sperimentale.

  1. Inserisci un URL di cui visualizzare l'anteprima.
  2. La pagina verrà incorporata come elemento <portal>.
  3. Fai clic sull'anteprima.
  4. L'anteprima verrà attivata dopo un'animazione.

Una GIF che mostra la demo del glitch dell&#39;utilizzo dei portali

Dai un'occhiata alle specifiche

Stiamo discutendo attivamente della specifica dei portali nel gruppo della community Web Incubation (WICG). Per iniziare rapidamente, dai un'occhiata ad alcuni degli scenari chiave. Ecco le tre funzionalità importanti da conoscere:

  • L'elemento <portal>: l'elemento HTML stesso. L'API è molto semplice. È costituito dall'attributo src, dalla funzione activate e da un'interfaccia per la messaggistica (postMessage). activate accetta un argomento facoltativo per passare i dati a <portal> al momento dell'attivazione.
  • Interfaccia portalHost: aggiunge un oggetto portalHost all'oggetto window. In questo modo puoi verificare se la pagina è incorporata come elemento <portal>. Fornisce inoltre un'interfaccia per l'invio di messaggi (postMessage) all'host.
  • Interfaccia PortalActivateEvent: un evento che viene attivato quando <portal> viene attivato. Esiste una funzione interessante chiamata adoptPredecessor che puoi utilizzare per recuperare la pagina precedente come elemento <portal>. In questo modo, puoi creare navigazioni fluide ed esperienze composte tra due pagine.

Andiamo oltre il pattern di utilizzo di base. Di seguito è riportato un elenco non esaustivo di cosa puoi fare con i portali, oltre al codice di esempio.

Personalizzare lo stile quando è incorporato come elemento <portal>

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

Messaggistica tra l'elemento <portal> e 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
});

Attivazione dell'elemento <portal> e ricezione dell'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;
});

Recupero del predecessore

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

Sapere che la tua pagina è stata adottata come predecessore

// 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
    });
  }
});

Combinando tutte le funzionalità supportate da Portali, puoi creare esperienze utente davvero straordinarie. Ad esempio, la demo riportata di seguito mostra come i portali possono offrire un'esperienza utente fluida tra un sito web e i contenuti incorporati di terze parti.

Casi d'uso e piani

Ci auguriamo che questo breve tour di Portals ti sia piaciuto. Non vediamo l'ora di scoprire cosa creerai. Ad esempio, ti consigliamo di iniziare a utilizzare i portali per le navigazioni non banali, ad esempio il pre-rendering della pagina del prodotto più venduto da una pagina della scheda della categoria di prodotto.

Un'altra cosa importante da sapere è che i portali possono essere utilizzati nelle navigazioni cross-origin, proprio come un <iframe>. Pertanto, se hai più siti web che fanno riferimento l'uno all'altro, puoi utilizzare anche i portali per creare una navigazione fluida tra due siti web diversi. Questo caso d'uso cross-origin è molto specifico per i portali e può persino migliorare l'esperienza utente delle SPA.

I feedback sono ben accetti

I portali sono pronti per la sperimentazione in Chrome 85 e versioni successive. I feedback della community sono fondamentali per la progettazione di nuove API, quindi provale e dicci cosa ne pensi. Se hai richieste di funzionalità o feedback, visita il repository GitHub di WICG.