Saiba como a API Portals proposta pode melhorar a UX de navegação.
Garantir que suas páginas carreguem rápido é fundamental para proporcionar uma boa experiência ao usuário. No entanto, uma área que geralmente ignoramos são as transições de página: o que os usuários veem quando se movem entre as páginas.
Uma nova proposta de API da plataforma da Web chamada Portals tem como objetivo ajudar com isso, simplificando a experiência à medida que os usuários navegam pelo seu site.
Confira os portais em ação:
Quais portais são ativados
Os aplicativos de página única (SPAs) oferecem boas transições, mas têm um custo maior de criação. Os aplicativos de várias páginas (MPAs, na sigla em inglês) são muito mais fáceis de criar, mas acabam com telas em branco entre as páginas.
Os portais oferecem o melhor dos dois mundos:
a baixa complexidade de uma MPA com as transições perfeitas de um SPA.
Pense neles como um <iframe>
, porque eles permitem a incorporação,
mas, diferentemente de um <iframe>
,
eles também têm recursos para navegar até o conteúdo.
Ver é acreditar: primeiro, confira o que apresentamos na Conferência de Desenvolvedores Chrome 2018:
Com as navegações clássicas, os usuários precisam aguardar com uma tela em branco
até que o navegador termine de renderizar o destino.
Com os portais, os usuários podem interagir com uma animação,
enquanto o <portal>
pré-renderiza o conteúdo e cria uma experiência de navegação perfeita.
Antes dos portais, poderíamos ter renderizado outra página usando um <iframe>
. Também poderíamos ter adicionado animações para mover o frame pela página. No entanto, <iframe>
não permite navegar até o conteúdo dela. Os portais preenchem essa lacuna, permitindo casos de uso interessantes.
Experimente os portais
Ativando via about://flags
Experimente os Portals no Chrome 85 e em versões posteriores exibindo uma sinalização experimental:
- Ative a sinalização
about://flags/#enable-portals
para navegações de mesma origem. - Para testar as navegações de origem cruzada, ative também a flag
about://flags/#enable-portals-cross-origin
.
Durante essa fase inicial do experimento dos portais,
também recomendamos usar um diretório de dados do usuário completamente separado para seus testes
configurando a
sinalização de linha de comando
--user-data-dir
.
Depois de ativar os portais, confirme nas DevTools se você tem o novo HTMLPortalElement
brilhante.
Implementar portais
Vamos dar uma olhada em um exemplo de implementação 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();
});
É simples assim. Teste esse código no console do DevTools. A página da Wikipédia será aberta.
Se você quiser criar algo como mostramos na Conferência de Desenvolvedores do Chrome e que funcione como a demonstração acima, o snippet a seguir será interessante.
// 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);
Também é fácil fazer a detecção de recursos para aprimorar progressivamente um site usando portais.
if ('HTMLPortalElement' in window) {
// If this is a platform that have Portals...
const portal = document.createElement('portal');
...
}
Para ter uma experiência rápida com os portais, use uskay-portals-demo.glitch.me. Acesse pelo Chrome 85 ou versões posteriores e ative a sinalização experimental.
- Insira o URL que você quer visualizar.
- A página será incorporada como um elemento
<portal>
. - Clique na visualização.
- A visualização será ativada após uma animação.
Confira a especificação
Estamos discutindo ativamente as especificações de portais no Web Incubation Community Group (WICG). Para aprender rapidamente, confira alguns dos principais cenários. Estes são os três recursos importantes para você se familiarizar:
- O elemento
<portal>
: o próprio elemento HTML. A API é muito simples. Ele consiste no atributosrc
, na funçãoactivate
e em uma interface para mensagens (postMessage
). Oactivate
usa um argumento opcional para transmitir dados ao<portal>
na ativação. - Interface
portalHost
:adiciona um objetoportalHost
aowindow
. Isso permite que você verifique se a página está incorporada como um elemento<portal>
. Ele também fornece uma interface para enviar mensagens (postMessage
) de volta ao host. - Interface PortalActivateEvent: um evento acionado quando o
<portal>
é ativado. Há uma função legal chamadaadoptPredecessor
que pode ser usada para recuperar a página anterior como um elemento<portal>
. Isso permite a criação de navegações e experiências compostas entre duas páginas.
Vamos analisar além do padrão de uso básico. Esta é uma lista com alguns exemplos do que você pode fazer com os portais, além do exemplo de código.
Personalize o estilo quando incorporado como um elemento <portal>
// Detect whether this page is hosted in a portal
if (window.portalHost) {
// Customize the UI when being embedded as a portal
}
Mensagens entre o elemento <portal>
e o 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
});
Ativar o elemento <portal>
e receber o 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;
});
Como recuperar o antecessor
// Listen to the portalactivate event
window.addEventListener('portalactivate', (evt) => {
// ... and creatively use the predecessor
const portal = evt.adoptPredecessor();
document.querySelector('someElm').appendChild(portal);
});
Saber que sua página foi adotada como predecessora
// 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
});
}
});
Ao combinar todos os recursos suportados pelos portais, é possível criar experiências do usuário muito sofisticadas. Por exemplo, a demonstração abaixo mostra como os portais podem permitir uma experiência do usuário perfeita entre um site e um conteúdo incorporado de terceiros.
Casos de uso e planos
Esperamos que você tenha gostado deste breve tour pelos portais. Mal podemos esperar para ver o que você vai inventar. Por exemplo, talvez você queira começar a usar portais para navegações não triviais, como: pré-renderizar a página do produto mais vendido em uma página de listagem de categorias de produtos.
Outra coisa importante é que os portais podem ser usados em navegações de origem cruzada, assim como um <iframe>
. Portanto, se você tiver vários sites que fazem referência mútua, também poderá usar portais para criar navegações perfeitas entre dois sites diferentes. Esse caso de uso de origem cruzada é muito exclusivo para portais e pode até melhorar a experiência do usuário em SPAs.
O feedback é bem-vindo
Os portais estão prontos para experimentação no Chrome 85 e em versões posteriores. O feedback da comunidade é crucial para o design de novas APIs. Teste e nos conte o que achou. Para enviar solicitações ou dar feedback sobre recursos, acesse o repositório da WICG no GitHub (em inglês).