जब दो अलग-अलग दस्तावेज़ों के बीच व्यू ट्रांज़िशन होता है, तो उसे क्रॉस-दस्तावेज़ व्यू ट्रांज़िशन कहा जाता है. आम तौर पर, ऐसा कई पेजों वाले ऐप्लिकेशन (एमपीए) में होता है. Chrome 126 से, Chrome में एक दस्तावेज़ से दूसरे दस्तावेज़ पर स्विच करने के दौरान, व्यू ट्रांज़िशन की सुविधा काम करती है.
ब्राउज़र के इस्तेमाल से जुड़ी सहायता
अलग-अलग दस्तावेज़ों के व्यू के बीच ट्रांज़िशन, एक ही दस्तावेज़ के व्यू के बीच ट्रांज़िशन के बिल्डिंग ब्लॉक और सिद्धांतों पर निर्भर करते हैं. ऐसा इसलिए किया गया है, ताकि:
- ब्राउज़र, उन एलिमेंट के स्नैपशॉट लेता है जिनमें पुराने और नए, दोनों पेजों पर यूनीक
view-transition-name
होता है. - रेंडरिंग रोकने पर, डीओएम अपडेट हो जाता है.
- आखिर में, ट्रांज़िशन सीएसएस ऐनिमेशन की मदद से काम करते हैं.
एक ही दस्तावेज़ के व्यू ट्रांज़िशन की तुलना में, अलग-अलग दस्तावेज़ों के व्यू ट्रांज़िशन में क्या अंतर है, यह जानने के लिए यह ध्यान रखें कि व्यू ट्रांज़िशन शुरू करने के लिए, आपको अलग-अलग दस्तावेज़ों के व्यू ट्रांज़िशन में document.startViewTransition
को कॉल करने की ज़रूरत नहीं है. इसके बजाय, क्रॉस-डॉक्यूमेंट व्यू ट्रांज़िशन का ट्रिगर, एक ही ऑरिजिन से एक पेज से दूसरे पेज पर नेविगेट करना है. आम तौर पर, आपकी वेबसाइट के उपयोगकर्ता किसी लिंक पर क्लिक करके यह कार्रवाई करते हैं.
दूसरे शब्दों में, दो दस्तावेज़ों के बीच व्यू ट्रांज़िशन शुरू करने के लिए, कोई एपीआई नहीं है. हालांकि, इसके लिए दो शर्तें पूरी करनी होंगी:
- दोनों दस्तावेज़ एक ही ऑरिजिन पर होने चाहिए.
- व्यू ट्रांज़िशन की अनुमति देने के लिए, दोनों पेजों को ऑप्ट-इन करना होगा.
इन दोनों शर्तों के बारे में इस दस्तावेज़ में आगे बताया गया है.
एक से ज़्यादा दस्तावेज़ों के व्यू के बीच ट्रांज़िशन, सिर्फ़ एक ही सोर्स के नेविगेशन तक सीमित हैं
एक दस्तावेज़ से दूसरे दस्तावेज़ में व्यू ट्रांज़िशन करने की सुविधा, सिर्फ़ एक ही सोर्स के नेविगेशन के लिए उपलब्ध है. अगर नेविगेशन में शामिल दोनों पेजों का ऑरिजिन एक ही है, तो नेविगेशन को एक ही ऑरिजिन वाला माना जाता है.
किसी पेज का ऑरिजिन, इस्तेमाल किए गए स्कीम, होस्टनेम, और पोर्ट का कॉम्बिनेशन होता है. इस बारे में web.dev पर जानकारी दी गई है.
उदाहरण के लिए, developer.chrome.com
से developer.chrome.com/blog
पर नेविगेट करते समय, आपके पास दस्तावेज़ के बीच व्यू ट्रांज़िशन करने का विकल्प होता है, क्योंकि ये एक ही सोर्स के हैं.
developer.chrome.com
से www.chrome.com
पर नेविगेट करते समय, आपको वह ट्रांज़िशन नहीं दिखेगा, क्योंकि ये क्रॉस-ऑरिजिन और एक ही साइट के यूआरएल हैं.
एक दस्तावेज़ से दूसरे दस्तावेज़ पर जाने के लिए ट्रांज़िशन की सुविधा के लिए ऑप्ट-इन करना ज़रूरी है
दो दस्तावेज़ों के बीच क्रॉस-दस्तावेज़ व्यू ट्रांज़िशन करने के लिए, दोनों पेजों को इसकी अनुमति देने के लिए ऑप्ट-इन करना होगा. ऐसा करने के लिए, सीएसएस में @view-transition
at-rule का इस्तेमाल किया जाता है.
@view-transition
at-rule में, navigation
डिस्क्रिप्टर को auto
पर सेट करें, ताकि एक ही ऑरिजिन वाले क्रॉस-दस्तावेज़ नेविगेशन के लिए व्यू ट्रांज़िशन चालू किए जा सकें.
@view-transition {
navigation: auto;
}
navigation
डिस्क्रिप्टर को auto
पर सेट करके, इन NavigationType के लिए व्यू ट्रांज़िशन की अनुमति देने के लिए ऑप्ट इन किया जा रहा है:
traverse
push
याreplace
, अगर उपयोगकर्ता ने ब्राउज़र के यूज़र इंटरफ़ेस (यूआई) के ज़रिए चालू करने की प्रोसेस शुरू नहीं की है.
auto
से बाहर रखे गए नेविगेशन में, यूआरएल पता बार का इस्तेमाल करके नेविगेट करना या बुकमार्क पर क्लिक करना शामिल है. साथ ही, उपयोगकर्ता या स्क्रिप्ट से शुरू किया गया कोई भी रीलोड भी शामिल है.
अगर नेविगेशन में बहुत ज़्यादा समय लगता है, तो Chrome के मामले में चार सेकंड से ज़्यादा समय लगने पर, व्यू ट्रांज़िशन को TimeoutError
DOMException
के साथ स्किप कर दिया जाता है.
एक से दूसरे दस्तावेज़ के व्यू के बीच ट्रांज़िशन करने की सुविधा का डेमो
स्टैक नेविगेटर का डेमो बनाने के लिए, व्यू ट्रांज़िशन का इस्तेमाल करने वाले इस डेमो को देखें. यहां document.startViewTransition()
को कोई कॉल नहीं किया गया है. व्यू ट्रांज़िशन, एक पेज से दूसरे पेज पर नेविगेट करने से ट्रिगर होते हैं.
एक दस्तावेज़ से दूसरे दस्तावेज़ के व्यू में ट्रांज़िशन करने की सुविधा को पसंद के मुताबिक बनाना
एक दस्तावेज़ से दूसरे दस्तावेज़ पर स्विच करने के दौरान होने वाले ट्रांज़िशन को पसंद के मुताबिक बनाने के लिए, वेब प्लैटफ़ॉर्म की कुछ सुविधाओं का इस्तेमाल किया जा सकता है.
ये सुविधाएं, व्यू ट्रांज़िशन एपीआई स्पेसिफ़िकेशन का हिस्सा नहीं हैं. हालांकि, इन्हें इसके साथ इस्तेमाल करने के लिए डिज़ाइन किया गया है.
pageswap
और pagereveal
इवेंट
क्रॉस-दस्तावेज़ व्यू ट्रांज़िशन को पसंद के मुताबिक बनाने के लिए, एचटीएमएल स्पेसिफ़िकेशन में दो नए इवेंट शामिल किए गए हैं: pageswap
और pagereveal
.
ये दोनों इवेंट, एक ही ऑरिजिन वाले हर क्रॉस-दस्तावेज़ नेविगेशन के लिए ट्रिगर होते हैं. भले ही, व्यू ट्रांज़िशन होने वाला हो या नहीं. अगर दो पेजों के बीच व्यू ट्रांज़िशन होने वाला है, तो इन इवेंट पर viewTransition
प्रॉपर्टी का इस्तेमाल करके ViewTransition
ऑब्जेक्ट को ऐक्सेस किया जा सकता है.
pageswap
इवेंट, पेज के आखिरी फ़्रेम के रेंडर होने से पहले ट्रिगर होता है. इसका इस्तेमाल करके, पुराने स्नैपशॉट लेने से ठीक पहले, आउटगोइंग पेज पर आखिरी समय में कुछ बदलाव किए जा सकते हैं.pagereveal
इवेंट, पेज को शुरू करने या फिर से चालू करने के बाद, पहली बार रेंडर करने से पहले ट्रिगर होता है. इसकी मदद से, नए स्नैपशॉट लेने से पहले, नए पेज को पसंद के मुताबिक बनाया जा सकता है.
उदाहरण के लिए, इन इवेंट का इस्तेमाल करके, कुछ view-transition-name
वैल्यू को तुरंत सेट या बदला जा सकता है. इसके अलावा, sessionStorage
से डेटा लिखकर और पढ़कर, एक दस्तावेज़ से दूसरे दस्तावेज़ में डेटा पास किया जा सकता है. इससे, व्यू ट्रांज़िशन के शुरू होने से पहले, उसे पसंद के मुताबिक बनाया जा सकता है.
let lastClickX, lastClickY;
document.addEventListener('click', (event) => {
if (event.target.tagName.toLowerCase() === 'a') return;
lastClickX = event.clientX;
lastClickY = event.clientY;
});
// Write position to storage on old page
window.addEventListener('pageswap', (event) => {
if (event.viewTransition && lastClick) {
sessionStorage.setItem('lastClickX', lastClickX);
sessionStorage.setItem('lastClickY', lastClickY);
}
});
// Read position from storage on new page
window.addEventListener('pagereveal', (event) => {
if (event.viewTransition) {
lastClickX = sessionStorage.getItem('lastClickX');
lastClickY = sessionStorage.getItem('lastClickY');
}
});
अगर आप चाहें, तो दोनों इवेंट में ट्रांज़िशन को छोड़ा जा सकता है.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
if (goodReasonToSkipTheViewTransition()) {
e.viewTransition.skipTransition();
}
}
}
pageswap
और pagereveal
में मौजूद ViewTransition
ऑब्जेक्ट, दो अलग-अलग ऑब्जेक्ट हैं. ये अलग-अलग वादे भी अलग-अलग तरीके से मैनेज करते हैं:
pageswap
: दस्तावेज़ छिपाने के बाद, पुरानेViewTransition
ऑब्जेक्ट को स्किप कर दिया जाता है. ऐसा होने पर,viewTransition.ready
अस्वीकार कर देता है औरviewTransition.finished
हल हो जाता है.pagereveal
: इस समय,updateCallBack
प्रॉमिस पूरा हो चुका है.viewTransition.ready
औरviewTransition.finished
प्रॉमिस का इस्तेमाल किया जा सकता है.
नेविगेशन चालू करने की जानकारी
pageswap
और pagereveal
, दोनों इवेंट में पुराने और नए पेजों के यूआरएल के आधार पर भी कार्रवाई की जा सकती है.
उदाहरण के लिए, एमपीए स्टैक नेविगेटर में, इस्तेमाल किए जाने वाले ऐनिमेशन का टाइप, नेविगेशन पाथ पर निर्भर करता है:
- खास जानकारी वाले पेज से ज़्यादा जानकारी वाले पेज पर जाने पर, नया कॉन्टेंट दाईं से बाईं ओर स्लाइड करना चाहिए.
- ज़्यादा जानकारी वाले पेज से खास जानकारी वाले पेज पर जाने पर, पुराने कॉन्टेंट को बाईं से दाईं ओर स्लाइड आउट करना होगा.
ऐसा करने के लिए, आपको उस नेविगेशन के बारे में जानकारी चाहिए जो pageswap
के मामले में होने वाला है या pagereveal
के मामले में अभी-अभी हुआ है.
इसके लिए, ब्राउज़र अब NavigationActivation
ऑब्जेक्ट दिखा सकते हैं. इनमें, एक ही सोर्स के नेविगेशन की जानकारी होती है. यह ऑब्जेक्ट, इस्तेमाल किए गए नेविगेशन टाइप, मौजूदा, और फ़ाइनल डेस्टिनेशन के इतिहास की एंट्री दिखाता है. ये एंट्री, नेविगेशन एपीआई के navigation.entries()
में मिलती हैं.
चालू किए गए पेज पर, navigation.activation
की मदद से इस ऑब्जेक्ट को ऐक्सेस किया जा सकता है. pageswap
इवेंट में, इसे e.activation
से ऐक्सेस किया जा सकता है.
यह प्रोफ़ाइल डेमो देखें. इसमें pageswap
और pagereveal
इवेंट में NavigationActivation
जानकारी का इस्तेमाल करके, उन एलिमेंट पर view-transition-name
वैल्यू सेट की जाती हैं जिन्हें व्यू ट्रांज़िशन में शामिल करना ज़रूरी है.
ऐसा करने से, आपको सूची में मौजूद हर आइटम को पहले से view-transition-name
के साथ सजाने की ज़रूरत नहीं पड़ती. इसके बजाय, यह सिर्फ़ ज़रूरी एलिमेंट पर, JavaScript का इस्तेमाल करके, ज़रूरत के हिसाब से होता है.
कोड इस तरह का है:
// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
const targetUrl = new URL(e.activation.entry.url);
// Navigating to a profile page
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the clicked row
document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';
// Remove view-transition-names after snapshots have been taken
// (this to deal with BFCache)
await e.viewTransition.finished;
document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
}
}
});
// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
const fromURL = new URL(navigation.activation.from.url);
const currentURL = new URL(navigation.activation.entry.url);
// Navigating from a profile page back to the homepage
if (isProfilePage(fromURL) && isHomePage(currentURL)) {
const profile = extractProfileNameFromUrl(currentURL);
// Set view-transition-name values on the elements in the list
document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';
// Remove names after snapshots have been taken
// so that we're ready for the next navigation
await e.viewTransition.ready;
document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
}
}
});
व्यू ट्रांज़िशन के चलने के बाद, कोड अपने-आप view-transition-name
वैल्यू हटाकर, साफ़ हो जाता है. इस तरह, पेज एक के बाद एक नेविगेशन के लिए तैयार हो जाता है और इतिहास को ट्रैवल करने की सुविधा भी दे सकता है.
इस काम में मदद पाने के लिए, इस यूटिलिटी फ़ंक्शन का इस्तेमाल करें. यह फ़ंक्शन, कुछ समय के लिए view-transition-name
सेट करता है.
const setTemporaryViewTransitionNames = async (entries, vtPromise) => {
for (const [$el, name] of entries) {
$el.style.viewTransitionName = name;
}
await vtPromise;
for (const [$el, name] of entries) {
$el.style.viewTransitionName = '';
}
}
पिछले कोड को अब इस तरह आसान बनाया जा सकता है:
// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
const targetUrl = new URL(e.activation.entry.url);
// Navigating to a profile page
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the clicked row
// Clean up after the page got replaced
setTemporaryViewTransitionNames([
[document.querySelector(`#${profile} span`), 'name'],
[document.querySelector(`#${profile} img`), 'avatar'],
], e.viewTransition.finished);
}
}
});
// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
const fromURL = new URL(navigation.activation.from.url);
const currentURL = new URL(navigation.activation.entry.url);
// Navigating from a profile page back to the homepage
if (isProfilePage(fromURL) && isHomePage(currentURL)) {
const profile = extractProfileNameFromUrl(currentURL);
// Set view-transition-name values on the elements in the list
// Clean up after the snapshots have been taken
setTemporaryViewTransitionNames([
[document.querySelector(`#${profile} span`), 'name'],
[document.querySelector(`#${profile} img`), 'avatar'],
], e.viewTransition.ready);
}
}
});
रेंडर ब्लॉकिंग की सुविधा का इस्तेमाल करके, कॉन्टेंट लोड होने का इंतज़ार करना
ब्राउज़र के इस्तेमाल से जुड़ी सहायता
कुछ मामलों में, हो सकता है कि आप किसी पेज को तब तक रेंडर न करना चाहें, जब तक कि नए DOM में कोई खास एलिमेंट मौजूद न हो. इससे फ़्लैशिंग की समस्या से बचा जा सकता है. साथ ही, यह भी पक्का किया जा सकता है कि जिस स्टेटस पर ऐनिमेशन किया जा रहा है वह स्थिर हो.
<head>
में, एक या उससे ज़्यादा एलिमेंट आईडी तय करें. ये ऐसे आईडी होने चाहिए जो पेज के पहली बार रेंडर होने से पहले मौजूद होने चाहिए. इसके लिए, नीचे दिए गए मेटा टैग का इस्तेमाल करें.
<link rel="expect" blocking="render" href="#section1">
इस मेटा टैग का मतलब है कि एलिमेंट डीओएम में मौजूद होना चाहिए, न कि कॉन्टेंट लोड होना चाहिए. उदाहरण के लिए, इमेज के लिए, डीओएम ट्री में तय किए गए id
के साथ <img>
टैग की मौजूदगी ही शर्त को 'सही' के तौर पर आकलन करने के लिए काफ़ी है. हो सकता है कि इमेज अब भी लोड हो रही हो.
रेंडर ब्लॉकिंग का पूरा इस्तेमाल करने से पहले, ध्यान रखें कि इंक्रीमेंटल रेंडरिंग, वेब का बुनियादी हिस्सा है. इसलिए, रेंडरिंग को ब्लॉक करने का विकल्प चुनते समय सावधानी बरतें. रेंडरिंग को ब्लॉक करने के असर का आकलन, हर मामले के हिसाब से करना होगा. डिफ़ॉल्ट रूप से, blocking=render
का इस्तेमाल तब तक न करें, जब तक आपके पास वेबसाइट की परफ़ॉर्मेंस की अहम जानकारी पर पड़ने वाले असर को मेज़र करने की सुविधा न हो.
अलग-अलग दस्तावेज़ों के व्यू के बीच ट्रांज़िशन के टाइप देखना
क्रॉस-दस्तावेज़ व्यू ट्रांज़िशन में, व्यू ट्रांज़िशन टाइप भी काम करते हैं. इनकी मदद से, ऐनिमेशन को पसंद के मुताबिक बनाया जा सकता है और यह तय किया जा सकता है कि कौनसे एलिमेंट कैप्चर किए जाएं.
उदाहरण के लिए, पेजेशन में अगले या पिछले पेज पर जाने पर, हो सकता है कि आप अलग-अलग ऐनिमेशन का इस्तेमाल करना चाहें. यह इस बात पर निर्भर करता है कि आपको क्रम में ऊपर वाले पेज पर जाना है या नीचे वाले पेज पर.
इन टाइप को पहले से सेट करने के लिए, @view-transition
at-rule में टाइप जोड़ें:
@view-transition {
navigation: auto;
types: slide, forwards;
}
टाइप को फ़्लाइट पर सेट करने के लिए, e.viewTransition.types
की वैल्यू में बदलाव करने के लिए pageswap
और pagereveal
इवेंट का इस्तेमाल करें.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
const transitionType = determineTransitionType(navigation.activation.from, navigation.activation.entry);
e.viewTransition.types.add(transitionType);
}
});
टाइप, पुराने पेज के ViewTransition
ऑब्जेक्ट से नए पेज के ViewTransition
ऑब्जेक्ट में अपने-आप ट्रांसफ़र नहीं होते. ऐनिमेशन उम्मीद के मुताबिक चलें, इसके लिए आपको कम से कम नए पेज पर इस्तेमाल करने के लिए टाइप तय करने होंगे.
इन टाइप के जवाब देने के लिए, :active-view-transition-type()
स्यूडो-क्लास सिलेक्टर का इस्तेमाल करें. इसका इस्तेमाल उसी तरह करें जिस तरह एक ही दस्तावेज़ के व्यू ट्रांज़िशन के लिए किया जाता है
/* Determine what gets captured when the type is forwards or backwards */
html:active-view-transition-type(forwards, backwards) {
:root {
view-transition-name: none;
}
article {
view-transition-name: content;
}
.pagination {
view-transition-name: pagination;
}
}
/* Animation styles for forwards type only */
html:active-view-transition-type(forwards) {
&::view-transition-old(content) {
animation-name: slide-out-to-left;
}
&::view-transition-new(content) {
animation-name: slide-in-from-right;
}
}
/* Animation styles for backwards type only */
html:active-view-transition-type(backwards) {
&::view-transition-old(content) {
animation-name: slide-out-to-right;
}
&::view-transition-new(content) {
animation-name: slide-in-from-left;
}
}
/* Animation styles for reload type only */
html:active-view-transition-type(reload) {
&::view-transition-old(root) {
animation-name: fade-out, scale-down;
}
&::view-transition-new(root) {
animation-delay: 0.25s;
animation-name: fade-in, scale-up;
}
}
टाइप सिर्फ़ चालू व्यू ट्रांज़िशन पर लागू होते हैं. इसलिए, व्यू ट्रांज़िशन पूरा होने पर, टाइप अपने-आप हट जाते हैं. इस वजह से, टाइप BFCache जैसी सुविधाओं के साथ अच्छी तरह काम करते हैं.
डेमो
यहां दिए गए पेज पर नंबर डालने के डेमो में, पेज का कॉन्टेंट आगे या पीछे की ओर स्लाइड करता है. यह इस बात पर निर्भर करता है कि आपने पेज के किस नंबर पर नेविगेट किया है.
pagereveal
और pageswap
इवेंट में, ट्रांज़िशन टाइप तय किया जाता है. इसके लिए, 'इससे' और 'इस पर' यूआरएल देखे जाते हैं.
const determineTransitionType = (fromNavigationEntry, toNavigationEntry) => {
const currentURL = new URL(fromNavigationEntry.url);
const destinationURL = new URL(toNavigationEntry.url);
const currentPathname = currentURL.pathname;
const destinationPathname = destinationURL.pathname;
if (currentPathname === destinationPathname) {
return "reload";
} else {
const currentPageIndex = extractPageIndexFromPath(currentPathname);
const destinationPageIndex = extractPageIndexFromPath(destinationPathname);
if (currentPageIndex > destinationPageIndex) {
return 'backwards';
}
if (currentPageIndex < destinationPageIndex) {
return 'forwards';
}
return 'unknown';
}
};
सुझाव/राय दें या शिकायत करें
डेवलपर के सुझाव, शिकायत या राय का हमेशा स्वागत है. सुझाव और सवाल शेयर करने के लिए, GitHub पर सीएसएस वर्किंग ग्रुप के साथ कोई समस्या दर्ज करें. अपनी समस्या के आगे [css-view-transitions]
जोड़ें.
अगर आपको कोई गड़बड़ी मिलती है, तो Chromium में गड़बड़ी की शिकायत करें.