DEV Community

Cover image for HTML <portal>: Chrome's weird navigational element
JS Bits with Bill
JS Bits with Bill

Posted on

HTML <portal>: Chrome's weird navigational element

What's a Portal?

You might have never heard of the HTML <portal> element. It's an experimental feature since Chrome 75 (June, 2019) and its proposal is in the draft stages. But what is it exactly? Essentially the <portal> is like a souped-up <iframe> and includes the ability to seamlessly navigate into embedded content.

Similar to an <iframe>, <portal> includes a src attribute which is the URL of the page you want to embed and the embedded content will look identical to an <iframe>. The <portal> is clickable but is not interactable since its purpose is to provide a smooth navigation into a prerended page - similar to the way most SPAs navigate. This differs from iframes which cannot immediately be navigated to without another request to the source. Clicking on a portal will navigate you right into all that content that's already loaded and rendered as the child inset of the parent document.

What's cool about portals is that they can be cross-origin, meaning you can create a portal to a different domain from where you're embedded it.

How To Use

So since portals are an experimental, we need to enable 2 flags in Chrome at about://flags/#enable-portals:

  • 🚩 Enable Portals
  • 🚩 Enable cross-origin Portals

Chrome will prompt you to relaunch your Browser and after doing so, you should see the HTMLPortalElement function available in your console:

So now let's create a basic portal! It's as easy as adding this HTML to your web page.

<portal src="https://theoatmeal.com"></portal>
Enter fullscreen mode Exit fullscreen mode

You can add styles to this element to adjust height, width, etc. but in its raw form you'll see the webpage from The Oatmeal embedded. When you click the portal, you navigate instantly to the source page and should not notice the normal "blink" you'd otherwise get from visiting a new Web page.

Let's Get Fancy

Here's a use case where we'll create a list of popular webcomics. Each block of content will show a preview image of the comic and when the user hovers over it our code will render a portal in place that can be clicked to navigate directly to the the webcomic's page:

First, the HTML:

<h2>Best Webcomics</h2>
<ol>
  <li>
    <h3>The Oatmeal</h3>
    <div 
      class="comic-container"
      data-src="https://theoatmeal.com/comics/forbidden_love"
    >
      <img src="/forbidden_love_big.png">
      <img class="spinner" src="/spinner.gif">
      <portal src=""></portal>
    </div>
  </li>

  <!-- Repeat lis for other webcomics -->
</ol>
Enter fullscreen mode Exit fullscreen mode

Notice we're using an empty src for the portal. To avoid unnecessary loading, we'll set the source in JavaScript only when the user hovers over .comic-container via the mouseenter event. As the source is being loaded, we'll show the spinner overlay so there's user feedback to show something is loading. Once fully loaded (by listening to the load event), we can display the portal over the existing image.

const blocks = document.querySelectorAll('.comic-container');
blocks.forEach(block => {
  block.addEventListener('mouseenter', e => {
    block.classList.add('hover');
    const portal = block.querySelector('portal');
    const { src } = block.dataset;
    portal.src = src;
  });

  // Add "mouseleave" listener to reset classes
});

const portals = document.querySelectorAll('portal');
portals.forEach(portal => {
  portal.addEventListener('load', e => {
    if (portal.closest('.comic-container').matches('.hover')) {
      portal.classList.add('show-portal');
    } 
  });
});
Enter fullscreen mode Exit fullscreen mode

From there, the user can click the portal and be instantly transported to the source page!

The default click behavior on a portal can also be prevented if you wanted to create a fancy animation the on click event and then call portal.activate() to activate the portal programmatically.

See full code here: https://github.com/doctafaustus/html-portal

Closing Thoughts

While portals give us a new way to preview and prerender pages, it's unclear if they'll ever be standard in browsers. My first thoughts about security were assuaged by reading that portals do not allow user interaction to channel through to the "portaled" document. Additionally, the embedded content will not have direct access to the host document. However, portals would still introduce yet another opportunity to create clever browser exploits, so a sound content security policy (CSP) would be recommended.

Nevertheless, they're still pretty cool!
Image description


Yo! I post byte-sized tips like these often. Follow me if you crave more! 🍿

I'm on Twitter, TikTok and I have a new debugging course out now!

Discussion (2)

Collapse
dailydevtips1 profile image
Chris Bongers

Oh man, this get's me hyped to try it out 🤯

Collapse
js_bits_bill profile image
JS Bits with Bill Author

You should!