Praktyczna obsługa portali: łatwa nawigacja w internecie

Dowiedz się, jak proponowany interfejs Portals API może poprawić wygodę nawigacji.

Yusuke Utsunomiya
Yusuke Utsunomiya

Zadbaj o to, by strony ładowały się szybko. Jednak często zapominamy o przejściach między stronami, czyli tym, co widzą użytkownicy przechodzący między stronami.

W tym celu powstał nowy interfejs API platformy internetowej o nazwie Portals, który ułatwi użytkownikom poruszanie się po Twojej witrynie.

Zobacz portale w akcji:

Bezproblemowe umieszczanie treści i nawigacja z portalami. Autor: Adam Argyle.

Funkcje dostępne w portalach

Aplikacje jednostronicowe zapewniają ładne przejścia, ale są bardziej skomplikowane w utworzeniu. Tworzenie aplikacji wielostronicowych (MPA) jest znacznie łatwiejsze, ale między stronami pojawiają się puste ekrany.

Portale łączy w sobie to, co najlepsze: to niska złożoność MPA i płynne przechodzenie ze SPA. Możesz je traktować jak <iframe>, ponieważ umożliwiają umieszczanie na stronach, ale w przeciwieństwie do <iframe> mają też funkcje umożliwiające przejście do treści.

Wierz wierzy, ale najpierw sprawdź, co zaprezentowaliśmy na Chrome Dev Summit 2018:

W klasycznej nawigacji użytkownicy muszą poczekać z pustym ekranem, aż przeglądarka zakończy renderowanie miejsca docelowego. Portale pozwalają użytkownikom zobaczyć animację, a <portal> wstępnie renderuje treści i zapewnia płynną nawigację.

Przed portalami mogliśmy renderować inną stronę przy użyciu <iframe>. Można też dodać animacje, które przesuwają ramkę po stronie. Element <iframe> nie pozwala jednak przejrzeć treści znajdujących się w nim. Portale wypełniają tę lukę, umożliwiając ciekawe przypadki użycia.

Wypróbuj portale

Włączanie na stronie about://flags

Wypróbuj portale w Chrome 85 i nowszych wersjach, odwracając flagę eksperymentalną:

  • Włącz flagę about://flags/#enable-portals na potrzeby nawigacji w tej samej domenie.
  • Aby przetestować nawigację między domenami, włącz dodatkowo flagę about://flags/#enable-portals-cross-origin.

Na wczesnym etapie eksperymentu z portalami zalecamy też używanie do testów zupełnie osobnego katalogu danych użytkownika przez ustawienie flagi wiersza poleceń --user-data-dir. Po włączeniu portali potwierdź w narzędziach deweloperskich, że masz nowy, błyszczący HTMLPortalElement.

Zrzut ekranu konsoli Narzędzi deweloperskich z widocznym obiektem HTMLPortalElement

Wdrażanie portali

Omówmy podstawowy przykład implementacji.

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

To naprawdę proste. Spróbuj wpisać ten kod w konsoli Narzędzi deweloperskich. Powinna się otworzyć strona w Wikipedii.

GIF przedstawiający wersję demonstracyjną w stylu portalu

Jeśli chcesz stworzyć coś, co pokazaliśmy na konferencji Chrome Dev Summit, a jednocześnie działa tak samo jak w przykładzie powyżej, przyda Ci się poniższy fragment kodu.

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

Możesz też łatwo wykrywać funkcje, aby stopniowo ulepszać witrynę za pomocą portali.

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

Jeśli chcesz szybko sprawdzić, jak działają portale, użyj uskay-portals-demo.glitch.me. Pamiętaj, aby otworzyć ją w Chrome 85 lub nowszej wersji i włączyć flagę eksperymentu.

  1. Wpisz adres URL, którego podgląd chcesz wyświetlić.
  2. Strona zostanie wtedy umieszczona jako element <portal>.
  3. Kliknij podgląd.
  4. Podgląd zostanie aktywowany po animacji.

GIF przedstawiający korzystanie z portali w wersji demonstracyjnej

Sprawdź specyfikację

Pracujemy aktywnie nad specyfikacją portali w grupie WICG (Web Incubation Community Group). Aby szybko sobie z nimi poradzić, zapoznaj się z niektórymi kluczowymi scenariuszami. Oto 3 ważne funkcje, z którymi warto się zapoznać:

  • Element <portal>: sam element HTML. Interfejs API jest bardzo prosty. Składa się z atrybutu src, funkcji activate i interfejsu do przesyłania wiadomości (postMessage). Po aktywacji activate przyjmuje opcjonalny argument, aby przekazać dane do <portal>.
  • Interfejs portalHost: dodaje obiekt portalHost do obiektu window. Pozwala to sprawdzić, czy strona jest umieszczona jako element <portal>. Udostępnia też interfejs do przesyłania wiadomości (postMessage) z powrotem do hosta.
  • Interfejs PortalActivateEvent: zdarzenie wywoływane po aktywowaniu zdarzenia <portal>. Dostępna jest funkcja adoptPredecessor, za pomocą której możesz pobrać poprzednią stronę jako element <portal>. Pozwala to na bezproblemowe poruszanie się po 2 stronach i w kolejne elementy interfejsu.

Nie zapominajmy o podstawowym wzorcu użycia. Oto (niekompletna) lista tego, co można osiągnąć dzięki portalom, wraz z przykładowym kodem.

Dostosuj styl umieszczony jako element <portal>

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

Komunikat między elementem <portal> a elementem 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
});

Aktywuję element <portal> i odbieram zdarzenie 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;
});

Pobieram poprzednika

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

Informacja o tym, że Twoja strona została przyjęta jako poprzednia

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

Łącząc wszystkie funkcje obsługiwane przez portale, możesz zapewniać użytkownikom niesamowite wrażenia. Na przykład poniższy przykład pokazuje, w jaki sposób portale mogą zapewnić użytkownikom bezproblemowe korzystanie z treści umieszczanych na stronie i przez firmy zewnętrzne.

Przypadki użycia i plany

Mamy nadzieję, że podoba Ci się ta krótka prezentacja portali. Nie możemy się już doczekać tego, co nam zaproponujesz. Na przykład możesz zacząć korzystać z portali w celu łatwej nawigacji, np. wstępnego renderowania strony bestsellera ze strony z listą kategorii produktów.

Pamiętaj też, że portali można używać do nawigacji między domenami, tak jak w <iframe>. Jeśli masz wiele witryn, które odwołują się do siebie, możesz też użyć portali, by płynnie przechodzić między dwiema różnymi witrynami. Ten przypadek użycia w innych domenach dotyczy tylko portali i może nawet poprawić wrażenia użytkowników aplikacji SPA.

Czekamy na Twoją opinię

Portale można eksperymentować w Chrome 85 i nowszych wersjach. Opinie społeczności są kluczowe przy opracowywaniu nowych interfejsów API, więc zachęcamy do ich wypróbowania i podzielenia się z nami swoją opinią. Jeśli masz jakieś prośby o dodanie funkcji lub chcesz przesłać opinię, skorzystaj z repozytorium WICG GitHub.