Praktyczna obsługa portali: łatwa nawigacja w internecie

Dowiedz się, jak proponowany interfejs Portals API może poprawić wrażenia użytkownika związane z nawigacją.

Yusuke Utsunomiya
Yusuke Utsunomiya

Szybkie wczytywanie stron to klucz do zapewnienia użytkownikom dobrych wrażeń. Często pomijamy jednak obszar przejścia między stronami – to, co użytkownicy widzą, gdy poruszają się po stronach.

Nowa propozycja interfejsu API platformy internetowej, czyli Portale, ma na celu ułatwić użytkownikom poruszanie się po Twojej witrynie.

Jak działają Portals:

Płynne umieszczanie i przechodzenie między elementami w Portalach. Utworzone przez Adama Argyle.

Co umożliwiają portale

Aplikacje jednostronicowe (SPA) zapewniają ładne przejścia, ale ich tworzenie jest bardziej skomplikowane. Aplikacje wielostronicowe (MPA) są znacznie łatwiejsze do tworzenia, ale kończą się pustymi ekranami między stronami.

Portale łączą zalety obu formatów: niską złożoność MPA z płynnymi przejściami SPA. Są one podobne do <iframe>, ponieważ umożliwiają umieszczanie, ale w przeciwieństwie do <iframe> mają też funkcje umożliwiające nawigację po treściach.

Widzieć, to wiedzieć: najpierw sprawdź, co prezentowaliśmy na konferencji Chrome Dev Summit 2018:

W przypadku klasycznej nawigacji użytkownicy muszą czekać na pustym ekranie, aż przeglądarka zakończy renderowanie miejsca docelowego. Dzięki Portals użytkownicy mogą oglądać animację, podczas gdy <portal> wstępnie renderuje treści i zapewnia płynną nawigację.

Przed Portalami można było renderować inną stronę za pomocą <iframe>. Mogliśmy też dodać animacje, aby przesuwać ramkę po stronie. Nie możesz jednak przeglądać zawartości <iframe>. Portale wypełniają tę lukę, umożliwiając ciekawe przypadki użycia.

Wypróbuj Portale

Włączanie za pomocą about://flags

Wypróbuj Portals w Chrome 85 lub nowszej wersji, włączając flagę eksperymentalną:

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

W tej wczesnej fazie eksperymentu dotyczącego Portals zalecamy też używanie całkowicie oddzielnego katalogu danych użytkownika do testów. Aby to zrobić, ustaw flagę wiersza poleceń --user-data-dir. Po włączeniu Portali sprawdź w Narzędziach deweloperskich, czy masz nową błyszczącą ikonę HTMLPortalElement.

Zrzut ekranu konsoli DevTools z elementem HTMLPortalElement

Implementacja portali

Przyjrzyjmy się podstawowemu przykładowi 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 bardzo proste. Spróbuj użyć tego kodu w konsoli Narzędzi deweloperskich. Powinna otworzyć się strona Wikipedia.

GIF z demonstracją stylu portalu

Jeśli chcesz stworzyć coś podobnego do tego, co pokazaliśmy na konferencji Chrome Dev Summit, czyli coś, co działa tak samo jak w powyższym demonstracyjnym pliku, ten fragment kodu może Cię zainteresować.

// 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ą Portals.

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

Jeśli chcesz szybko sprawdzić, jak działa Portals, skorzystaj z uskay-portals-demo.glitch.me. Upewnij się, że korzystasz z Chrome w wersji 85 lub nowszej i włącz opcję eksperymentalną.

  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 pokazujący używanie demo glitcha w Portalach

Sprawdź specyfikację

W ramach grupy społeczności Web Incubation Community Group (WICG) aktywnie omawiamy specyfikację Portals. Aby szybko się zapoznać z tą funkcją, zapoznaj się z kilkoma kluczowymi scenariuszami. Oto 3 ważne funkcje, które warto poznać:

  • 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). Funkcja activate przyjmuje opcjonalny argument, który służy do przekazywania danych do funkcji <portal> po jej aktywacji.
  • Interfejs portalHost: dodaje obiekt portalHost do obiektu window. Dzięki temu możesz sprawdzić, czy strona jest umieszczona jako element <portal>. Zapewnia też interfejs do wysyłania wiadomości (postMessage) do gospodarza.
  • Interfejs PortalActivateEvent: zdarzenie, które uruchamia się, gdy aktywowane jest <portal>. Istnieje przydatna funkcja adoptPredecessor, która umożliwia pobranie poprzedniej strony jako elementu <portal>. Dzięki temu możesz tworzyć płynną nawigację i kompozycje między 2 stronami.

Przyjrzyjmy się bliżej podstawowym wzorom użytkowania. Oto niepełna lista tego, co możesz osiągnąć dzięki portom, wraz z przykładowym kodem.

Dostosowywanie stylu podczas umieszczania jako elementu <portal>

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

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

Aktywowanie elementu <portal> i odbieranie zdarzenia 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;
});

Pobieranie poprzednika

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

Wiesz, że Twoja strona została przyjęta jako strona 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 Portals, możesz tworzyć naprawdę atrakcyjne wrażenia dla użytkowników. Na przykład w tym filmie pokazujemy, jak Portale mogą zapewnić użytkownikom płynne wrażenia podczas korzystania z witryny i osadzonych treści innych firm.

Przypadki użycia i plany

Mamy nadzieję, że spodobała Ci się ta krótka prezentacja Portals. Nie możemy się doczekać, żeby zobaczyć, co wymyślisz. Możesz na przykład zacząć używać portali do skomplikowanych działań nawigacyjnych, takich jak wstępna renderyzacja strony bestsellerowego produktu na stronie kategorii produktów.

Kolejną ważną rzeczą jest to, że portali można używać w przeglądaniu między domenami, tak jak w przypadku <iframe>. Jeśli masz wiele witryn, które odwołują się do siebie nawzajem, możesz też używać portali, aby zapewnić płynne przechodzenie między tymi witrynami. Ten przypadek użycia w wielu domenach jest bardzo charakterystyczny dla Portals i może nawet poprawić wrażenia użytkowników korzystających z aplikacji SPA.

Czekamy na Twoją opinię

Portale są gotowe do eksperymentowania w Chrome 85 i nowszych wersjach. Opinie społeczności są kluczowe dla projektowania nowych interfejsów API, dlatego wypróbuj je i powiedz nam, co o nich myślisz. Jeśli chcesz zasugerować nową funkcję lub podzielić się opinią, odwiedź repozytorium WICG na GitHubie.