Langsung menggunakan Portal: navigasi yang lancar di web

Pelajari cara Portals API yang diusulkan dapat meningkatkan UX navigasi Anda.

Yusuke Utsunomiya
Yusuke Utsunomiya

Memastikan halaman Anda dimuat dengan cepat adalah kunci untuk memberikan pengalaman pengguna yang baik. Namun, ada satu area yang sering kita abaikan, yaitu transisi halaman—yang dilihat pengguna saat berpindah antarhalaman.

Proposal API platform web baru yang disebut Portal bertujuan untuk membantu hal ini dengan menyederhanakan pengalaman saat pengguna menjelajahi seluruh situs Anda.

Lihat cara kerja Portal:

Penyisipan dan navigasi yang lancar dengan Portal. Dibuat oleh Adam Argyle.

Fungsi Portal

Aplikasi Web Satu Halaman (SPA) menawarkan transisi yang bagus, tetapi dengan biaya kompleksitas yang lebih tinggi untuk build. Aplikasi Multi-halaman (MPA) jauh lebih mudah dibuat, tetapi Anda akan mendapatkan layar kosong di antara halaman.

Portal menawarkan solusi terbaik dari kedua hal tersebut: kompleksitas MPA yang rendah dengan transisi SPA yang lancar. Anggaplah seperti <iframe> karena memungkinkan penyematan, tetapi tidak seperti <iframe>, objek ini juga dilengkapi dengan fitur untuk membuka kontennya.

Melihat adalah percaya: lihat terlebih dahulu apa yang kami tampilkan di Chrome Dev Summit 2018:

Dengan navigasi klasik, pengguna harus menunggu dengan layar kosong hingga browser selesai merender tujuan. Dengan Portal, pengguna dapat menikmati animasi, sedangkan <portal> melakukan pra-render konten dan menciptakan pengalaman navigasi yang lancar.

Sebelum Portal, kita dapat merender halaman lain menggunakan <iframe>. Kita juga dapat menambahkan animasi untuk memindahkan bingkai di sekitar halaman. Namun, <iframe> tidak akan mengizinkan Anda membuka kontennya. Portal menutup kesenjangan ini, sehingga memungkinkan kasus penggunaan yang menarik.

Mencoba Portal

Mengaktifkan melalui about://flags

Coba Portal di Chrome 85 dan versi yang lebih baru dengan mengaktifkan flag eksperimental:

  • Aktifkan flag about://flags/#enable-portals untuk navigasi dengan origin yang sama.
  • Untuk menguji navigasi lintas-asal, aktifkan juga tanda about://flags/#enable-portals-cross-origin.

Selama fase awal eksperimen Portal ini, sebaiknya gunakan direktori data pengguna yang sepenuhnya terpisah untuk pengujian Anda dengan menetapkan flag command line --user-data-dir. Setelah Portal diaktifkan, konfirmasi di DevTools bahwa Anda memiliki HTMLPortalElement baru yang baru.

Screenshot konsol DevTools yang menampilkan HTMLPortalElement

Mengimplementasikan Portal

Mari kita pelajari contoh penerapan dasar.

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

Semudah itu. Coba kode ini di konsol DevTools, halaman Wikipedia akan terbuka.

GIF demo gaya portal pratinjau

Jika Anda ingin membuat sesuatu seperti yang kami tunjukkan di Chrome Dev Summit yang berfungsi seperti demo di atas, cuplikan berikut akan menarik.

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

Deteksi fitur untuk meningkatkan kualitas situs secara bertahap menggunakan Portal juga mudah dilakukan.

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

Jika Anda ingin merasakan pengalaman Portal dengan cepat, coba gunakan uskay-portals-demo.glitch.me. Pastikan Anda mengaksesnya dengan Chrome versi 85 atau yang lebih baru dan mengaktifkan flag eksperimental.

  1. Masukkan URL yang ingin Anda lihat pratinjaunya.
  2. Halaman kemudian akan disematkan sebagai elemen <portal>.
  3. Klik pratinjau.
  4. Pratinjau akan diaktifkan setelah animasi.

Gif menggunakan demo glitch menggunakan Portal

Lihat spesifikasi

Kami secara aktif membahas spesifikasi Portal di Grup Komunitas Inkubasi Web (WICG). Untuk memahami dengan cepat, lihat beberapa skenario utama. Berikut adalah tiga fitur penting yang perlu Anda pelajari:

  • Elemen <portal>: Elemen HTML itu sendiri. API-nya sangat sederhana. Fungsi ini terdiri dari atribut src, fungsi activate, dan antarmuka untuk pesan (postMessage). activate menggunakan argumen opsional untuk meneruskan data ke <portal> saat diaktifkan.
  • Antarmuka portalHost: Menambahkan objek portalHost ke objek window. Tindakan ini memungkinkan Anda memeriksa apakah halaman disematkan sebagai elemen <portal>. Antarmuka ini juga menyediakan antarmuka untuk mengirim pesan (postMessage) kembali ke host.
  • Antarmuka PortalActivateEvent: Peristiwa yang diaktifkan saat <portal> diaktifkan. Ada fungsi rapi bernama adoptPredecessor yang dapat Anda gunakan untuk mengambil halaman sebelumnya sebagai elemen <portal>. Hal ini memungkinkan Anda membuat navigasi yang lancar dan pengalaman yang disusun antara dua halaman.

Mari kita lihat lebih dari sekadar pola penggunaan dasar. Berikut adalah daftar tidak lengkap tentang hal yang dapat Anda capai dengan Portal beserta contoh kodenya.

Menyesuaikan gaya saat disematkan sebagai elemen <portal>

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

Pesan antara elemen <portal> dan 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
});

Mengaktifkan elemen <portal> dan menerima peristiwa 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;
});

Mengambil pendahulu

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

Mengetahui bahwa halaman Anda diadopsi sebagai halaman sebelumnya

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

Dengan menggabungkan semua fitur yang didukung oleh Portal, Anda dapat membuat pengalaman pengguna yang sangat menarik. Misalnya, demo di bawah menunjukkan cara Portal dapat memberikan pengalaman pengguna yang lancar antara situs dan konten sematan pihak ketiga.

Kasus penggunaan dan rencana

Kami harap Anda menyukai tur singkat Portal ini. Kami tidak sabar ingin melihat kreasi Anda. Misalnya, Anda mungkin ingin mulai menggunakan Portal untuk navigasi yang tidak umum seperti: pra-rendering halaman untuk produk terlaris Anda dari halaman listingan kategori produk.

Hal penting lainnya yang perlu diketahui adalah bahwa Portal dapat digunakan dalam navigasi lintas-asal, seperti <iframe>. Jadi, jika Anda memiliki beberapa situs yang saling mereferensikan, Anda juga dapat menggunakan Portal untuk membuat navigasi yang lancar di antara dua situs yang berbeda. Kasus penggunaan lintas-asal ini sangat unik untuk Portal, dan bahkan dapat meningkatkan pengalaman pengguna SPA.

Kami menerima masukan

Portal siap untuk eksperimen di Chrome 85 dan versi yang lebih baru. Masukan dari komunitas sangat penting untuk desain API baru, jadi coba dan sampaikan pendapat Anda kepada kami. Jika Anda memiliki permintaan fitur atau masukan, buka repositori GitHub WICG.