提案されている Portals API がナビゲーションの UX を改善する方法について学びます。
優れたユーザー エクスペリエンスを提供するには、ページの読み込みを速くすることが重要です。しかし、見落としがちなのがページ遷移です。ユーザーがページ間を移動する際に表示されるものです。
新しいウェブ プラットフォーム API プロポーザルである ポータルは、ユーザーがサイト内を移動する際のエクスペリエンスを効率化することで、この問題を解決することを目的としています。
ポータルの動作を確認:
ポータルで可能になること
シングルページ アプリケーション(SPA)は、優れた遷移を提供しますが、構築の複雑さが増します。マルチページ アプリケーション(MPA)は作成がはるかに簡単ですが、ページ間に空白の画面が表示されます。
ポータルは、MPA の複雑さの低さと SPA のシームレスな遷移という、両方の長所を備えています。埋め込みが可能な点では <iframe>
に似ていますが、<iframe>
とは異なり、コンテンツに移動するための機能も備わっています。
百聞は一見にしかず: まず、Chrome Dev Summit 2018 で紹介された内容をご覧ください。
従来のナビゲーションでは、ブラウザがリンク先のレンダリングを完了するまで、ユーザーは空白の画面を待つ必要があります。Portals ではユーザーにアニメーションを表示できますが、<portal>
はコンテンツを事前レンダリングしてシームレスなナビゲーション エクスペリエンスを実現します。
ポータルを導入する前は、<iframe>
を使用して別のページをレンダリングすることができました。ページ内でフレームを移動するアニメーションを追加することもできます。ただし、<iframe>
ではコンテンツに移動できません。ポータルは、このギャップを埋めて、興味深いユースケースを可能にします。
ポータルを試す
about://flags から有効にする
Chrome 85 以降のバージョンでポータルをお試しいただくには、試験運用版フラグを有効にします。
- 同じオリジンのナビゲーションに対して
about://flags/#enable-portals
フラグを有効にします。 - クロスオリジン ナビゲーションをテストするには、
about://flags/#enable-portals-cross-origin
フラグも有効にします。
ポータル テストのこの初期段階では、--user-data-dir
コマンドライン フラグを設定して、テストに完全に別のユーザーデータ ディレクトリを使用することもおすすめします。ポータルを有効にしたら、DevTools で新しい HTMLPortalElement
が使用されていることを確認します。
ポータルを実装する
基本的な実装例を見ていきましょう。
// 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();
});
手順は簡単です。DevTools コンソールでこのコードを試すと、Wikipedia のページが開きます。
Chrome Dev Summit で紹介した、上記のデモと同様の機能を構築したい場合は、次のスニペットが役に立ちます。
// 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);
また、ポータルを使用して特徴検出を行い、ウェブサイトを段階的に拡張することも簡単です。
if ('HTMLPortalElement' in window) {
// If this is a platform that have Portals...
const portal = document.createElement('portal');
...
}
Portals の使用感をすばやく確認するには、uskay-portals-demo.glitch.me をお試しください。Chrome 85 以降のバージョンでアクセスし、試験運用版フラグをオンにしてください。
- プレビューする URL を入力します。
- ページは
<portal>
要素として埋め込まれます。 - プレビューをクリックします。
- プレビューはアニメーションの後に有効になります。
仕様を確認する
Google は、Web Incubation Community Group(WICG)でポータルの仕様について積極的に議論しています。すぐに使いこなせるように、主なシナリオのいくつかを見てみましょう。以下に、理解しておくべき 3 つの重要な機能について説明します。
<portal>
要素: HTML 要素自体。API は非常にシンプルです。これは、src
属性、activate
関数、メッセージ用インターフェース(postMessage
)で構成されます。activate
は、アクティベーション時にデータを<portal>
に渡すオプションの引数です。portalHost
インターフェース:portalHost
オブジェクトをwindow
オブジェクトに追加します。これにより、ページが<portal>
要素として埋め込まれているかどうかを確認できます。また、ホストにメッセージを返すためのインターフェース(postMessage
)も提供します。- PortalActivateEvent インターフェース:
<portal>
が有効化されたときに発生するイベント。adoptPredecessor
という便利な関数があり、これを使用して前のページを<portal>
要素として取得できます。これにより、2 つのページ間でシームレスなナビゲーションと合成されたエクスペリエンスを構築できます。
基本的な使用パターン以外にも、ポータルでできることの例とサンプルコードを以下に示します。
<portal>
要素として埋め込む際にスタイルをカスタマイズする
// Detect whether this page is hosted in a portal
if (window.portalHost) {
// Customize the UI when being embedded as a portal
}
<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
});
<portal>
要素を有効にして 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;
});
前任者の取得
// Listen to the portalactivate event
window.addEventListener('portalactivate', (evt) => {
// ... and creatively use the predecessor
const portal = evt.adoptPredecessor();
document.querySelector('someElm').appendChild(portal);
});
ページが前任者として採用されたことを知る
// 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
});
}
});
ポータルでサポートされているすべての機能を組み合わせることで、洗練されたユーザー エクスペリエンスを構築できます。たとえば、次のデモは、ポータルでウェブサイトとサードパーティの埋め込みコンテンツをシームレスに連携させる方法を示しています。
ユースケースとプラン
ポータルについての簡単なガイドがお役に立てば幸いです。ぜひお試しください。たとえば、ポータルは、商品カテゴリのリスト ページからベストセラー商品のページを事前レンダリングするなど、重要なナビゲーションに使い始めることができます。
また、Portal は <iframe>
と同様に、クロスオリジン ナビゲーションで使用できます。相互参照する複数のウェブサイトがある場合は、ポータルを使用して 2 つの異なるウェブサイトをシームレスに移動することもできます。このクロスオリジンのユースケースはポータルに固有のものであり、SPA のユーザー エクスペリエンスの向上にもつながります。
フィードバックをお待ちしています
ポータルは、Chrome 85 以降のバージョンでテストできます。新しい API の設計にはコミュニティからのフィードバックが不可欠です。ぜひお試しいただき、ご意見をお寄せください。機能のリクエストやフィードバックがある場合は、WICG GitHub リポジトリにアクセスしてください。