एक पेज के ऐप्लिकेशन के लिए, एक ही दस्तावेज़ वाले व्यू में ट्रांज़िशन

पब्लिश होने की तारीख: 17 अगस्त, 2021, पिछली बार अपडेट किए जाने की तारीख: 25 सितंबर, 2024

जब किसी एक दस्तावेज़ पर व्यू ट्रांज़िशन चलता है, तो उसे एक ही दस्तावेज़ पर होने वाला व्यू ट्रांज़िशन कहा जाता है. आम तौर पर, ऐसा एक पेज वाले ऐप्लिकेशन (एसपीए) में होता है. इनमें DOM को अपडेट करने के लिए JavaScript का इस्तेमाल किया जाता है. Chrome 111 से, Chrome में एक ही दस्तावेज़ में व्यू ट्रांज़िशन की सुविधा काम करती है.

एक ही दस्तावेज़ में व्यू ट्रांज़िशन को ट्रिगर करने के लिए, document.startViewTransition को कॉल करें:

function handleClick(e) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow();
    return;
  }

  // With a View Transition:
  document.startViewTransition(() => updateTheDOMSomehow());
}

इस फ़ंक्शन को चालू करने पर, ब्राउज़र उन सभी एलिमेंट के स्नैपशॉट अपने-आप कैप्चर कर लेता है जिन पर view-transition-name सीएसएस प्रॉपर्टी का एलान किया गया है.

इसके बाद, यह पास किए गए कॉलबैक को लागू करता है, जो DOM को अपडेट करता है. इसके बाद, यह नई स्थिति के स्नैपशॉट लेता है.

इसके बाद, इन स्नैपशॉट को सूडो-एलिमेंट के ट्री में व्यवस्थित किया जाता है. साथ ही, सीएसएस ऐनिमेशन की मदद से इन्हें ऐनिमेट किया जाता है. स्नैपशॉट के जोड़े, पुरानी और नई स्थिति के बीच आसानी से ट्रांज़िशन करते हैं. इस दौरान, वे अपनी पुरानी जगह और साइज़ से नई जगह पर चले जाते हैं. साथ ही, उनका कॉन्टेंट क्रॉसफ़ेड हो जाता है. अगर आपको एनिमेशन को पसंद के मुताबिक बनाना है, तो सीएसएस का इस्तेमाल किया जा सकता है.


डिफ़ॉल्ट ट्रांज़िशन: क्रॉस-फ़ेड

डिफ़ॉल्ट व्यू ट्रांज़िशन, क्रॉस-फ़ेड होता है. इसलिए, यह एपीआई के बारे में अच्छी जानकारी देता है:

function spaNavigate(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // With a transition:
  document.startViewTransition(() => updateTheDOMSomehow(data));
}

यहां updateTheDOMSomehow, DOM को नई स्थिति में बदलता है. हालांकि, ऐसा अपनी पसंद के हिसाब से किया जा सकता है. उदाहरण के लिए, एलिमेंट जोड़े या हटाए जा सकते हैं, क्लास के नाम बदले जा सकते हैं या स्टाइल बदली जा सकती हैं.

इसके बाद, पेज इस तरह फ़ेड हो जाते हैं:

यह डिफ़ॉल्ट क्रॉस-फ़ेड होता है. कम से कम डेमो. सोर्स.

ठीक है, क्रॉस-फ़ेड उतना अच्छा नहीं है. अच्छी बात यह है कि ट्रांज़िशन को पसंद के मुताबिक बनाया जा सकता है. हालांकि, इससे पहले आपको यह समझना होगा कि यह बेसिक क्रॉस-फ़ेड कैसे काम करता है.


ये ट्रांज़िशन कैसे काम करते हैं

आइए, पिछले कोड सैंपल को अपडेट करें.

document.startViewTransition(() => updateTheDOMSomehow(data));

.startViewTransition() को कॉल करने पर, एपीआई पेज की मौजूदा स्थिति को कैप्चर करता है. इसमें स्नैपशॉट लेना भी शामिल है.

यह प्रोसेस पूरी होने के बाद, .startViewTransition() को पास किए गए कॉलबैक को कॉल किया जाता है. इसी जगह पर DOM में बदलाव किया जाता है. इसके बाद, एपीआई पेज की नई स्थिति को कैप्चर करता है.

नई स्थिति कैप्चर होने के बाद, एपीआई इस तरह का सूडो-एलिमेंट ट्री बनाता है:

::view-transition
└─ ::view-transition-group(root)
   └─ ::view-transition-image-pair(root)
      ├─ ::view-transition-old(root)
      └─ ::view-transition-new(root)

::view-transition, पेज पर मौजूद अन्य सभी चीज़ों के ऊपर एक ओवरले के तौर पर दिखता है. अगर आपको ट्रांज़िशन के लिए बैकग्राउंड का रंग सेट करना है, तो यह विकल्प काम का है.

::view-transition-old(root) पुराने व्यू का स्क्रीनशॉट है. वहीं, ::view-transition-new(root) नए व्यू का लाइव वर्शन है. दोनों को सीएसएस 'बदला गया कॉन्टेंट' (जैसे कि <img>) के तौर पर रेंडर किया जाता है.

पुराना व्यू opacity: 1 से opacity: 0 तक ऐनिमेट होता है, जबकि नया व्यू opacity: 0 से opacity: 1 तक ऐनिमेट होता है. इससे क्रॉस-फ़ेड इफ़ेक्ट बनता है.

सभी ऐनिमेशन, सीएसएस ऐनिमेशन का इस्तेमाल करके किए जाते हैं. इसलिए, इन्हें सीएसएस की मदद से पसंद के मुताबिक बनाया जा सकता है.

ट्रांज़िशन को पसंद के मुताबिक बनाना

सीएसएस की मदद से, व्यू ट्रांज़िशन के सभी सूडो-एलिमेंट को टारगेट किया जा सकता है. साथ ही, सीएसएस का इस्तेमाल करके ऐनिमेशन तय किए जाते हैं. इसलिए, सीएसएस ऐनिमेशन की मौजूदा प्रॉपर्टी का इस्तेमाल करके, उनमें बदलाव किया जा सकता है. उदाहरण के लिए:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 5s;
}

इस एक बदलाव के बाद, अब फ़ेड होने की प्रोसेस बहुत धीमी हो गई है:

लंबा क्रॉस-फ़ेड. कम से कम डेमो. सोर्स.

ठीक है, यह अब भी बहुत अच्छा नहीं है. इसके बजाय, यहां दिए गए कोड में Material Design के शेयर किए गए ऐक्सिस ट्रांज़िशन को लागू किया गया है:

@keyframes fade-in {
  from { opacity: 0; }
}

@keyframes fade-out {
  to { opacity: 0; }
}

@keyframes slide-from-right {
  from { transform: translateX(30px); }
}

@keyframes slide-to-left {
  to { transform: translateX(-30px); }
}

::view-transition-old(root) {
  animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}

::view-transition-new(root) {
  animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

और यह रहा नतीजा:

शेयर किए गए ऐक्सिस का ट्रांज़िशन. कम से कम डेमो. सोर्स.

एक से ज़्यादा एलिमेंट को ट्रांज़िशन करना

पिछले डेमो में, पूरे पेज को शेयर किए गए ऐक्सिस ट्रांज़िशन में शामिल किया गया है. यह तरीका पेज के ज़्यादातर हिस्से के लिए काम करता है. हालांकि, हेडिंग के लिए यह सही नहीं लगता, क्योंकि यह स्लाइड आउट होकर फिर से स्लाइड इन हो जाती है.

इससे बचने के लिए, पेज के बाकी हिस्से से हेडर को अलग किया जा सकता है, ताकि उसे अलग से ऐनिमेट किया जा सके. इसके लिए, एलिमेंट को view-transition-name असाइन किया जाता है.

.main-header {
  view-transition-name: main-header;
}

view-transition-name की वैल्यू कुछ भी हो सकती है. हालांकि, none नहीं होनी चाहिए. इसका मतलब है कि ट्रांज़िशन का कोई नाम नहीं है. इसका इस्तेमाल, ट्रांज़िशन के दौरान एलिमेंट की खास तौर पर पहचान करने के लिए किया जाता है.

और इसका नतीजा यह है कि:

फ़िक्स्ड हेडर के साथ शेयर किए गए ऐक्सिस का ट्रांज़िशन. कम से कम डेमो. सोर्स.

अब हेडर अपनी जगह पर बना रहता है और क्रॉस-फ़ेड होता है.

सीएसएस के इस एलान की वजह से, सूडो-एलिमेंट ट्री में बदलाव हुआ है:

::view-transition
├─ ::view-transition-group(root)
│  └─ ::view-transition-image-pair(root)
│     ├─ ::view-transition-old(root)
│     └─ ::view-transition-new(root)
└─ ::view-transition-group(main-header)
   └─ ::view-transition-image-pair(main-header)
      ├─ ::view-transition-old(main-header)
      └─ ::view-transition-new(main-header)

अब दो ट्रांज़िशन ग्रुप हैं. एक हेडर के लिए और दूसरा बाकी के लिए. सीएसएस की मदद से, इन्हें अलग-अलग तरीके से टारगेट किया जा सकता है. साथ ही, इन्हें अलग-अलग ट्रांज़िशन दिए जा सकते हैं. हालांकि, इस मामले में main-header को डिफ़ॉल्ट ट्रांज़िशन के साथ छोड़ दिया गया था, जो कि क्रॉस-फ़ेड है.

ठीक है, डिफ़ॉल्ट ट्रांज़िशन सिर्फ़ क्रॉस फ़ेड नहीं होता. इसके अलावा, ::view-transition-group भी ट्रांज़िशन करता है:

  • पोज़िशन और ट्रांसफ़ॉर्म करना (transform का इस्तेमाल करके)
  • चौड़ाई
  • ऊंचाई

अब तक इससे कोई फ़र्क़ नहीं पड़ा, क्योंकि हेडर का साइज़ और पोज़िशन, DOM में बदलाव होने के बाद भी एक जैसी है. हालांकि, हेडर में मौजूद टेक्स्ट को भी निकाला जा सकता है:

.main-header-text {
  view-transition-name: main-header-text;
  width: fit-content;
}

fit-content का इस्तेमाल इसलिए किया जाता है, ताकि एलिमेंट का साइज़ टेक्स्ट के साइज़ के बराबर हो. ऐसा न हो कि वह बाकी चौड़ाई तक फैल जाए. इसके बिना, बैक ऐरो बटन पर क्लिक करने से, हेडर टेक्स्ट एलिमेंट का साइज़ कम हो जाता है. हालांकि, दोनों पेजों पर इसका साइज़ एक जैसा होना चाहिए.

इसलिए, अब हमारे पास तीन हिस्से हैं:

::view-transition
├─ ::view-transition-group(root)
│  └─ …
├─ ::view-transition-group(main-header)
│  └─ …
└─ ::view-transition-group(main-header-text)
   └─ …

हालांकि, डिफ़ॉल्ट सेटिंग का इस्तेमाल करने पर:

स्लाइडिंग हेडर टेक्स्ट. कम से कम डेमो. सोर्स.

अब हेडिंग का टेक्स्ट, बैक बटन के लिए जगह बनाने के लिए थोड़ा स्लाइड करता है.


view-transition-class का इस्तेमाल करके, एक ही तरह से कई छद्म-तत्वों को ऐनिमेट करना

Browser Support

  • Chrome: 125.
  • Edge: 125.
  • Firefox Technology Preview: supported.
  • Safari: 18.2.

Source

मान लें कि आपके पास कई कार्ड वाली व्यू ट्रांज़िशन सुविधा है. हालांकि, पेज पर एक टाइटल भी है. टाइटल को छोड़कर, सभी कार्ड में ऐनिमेशन जोड़ने के लिए, आपको एक ऐसा सिलेक्टर लिखना होगा जो हर कार्ड को टारगेट करे.

h1 {
    view-transition-name: title;
}
::view-transition-group(title) {
    animation-timing-function: ease-in-out;
}

#card1 { view-transition-name: card1; }
#card2 { view-transition-name: card2; }
#card3 { view-transition-name: card3; }
#card4 { view-transition-name: card4; }

#card20 { view-transition-name: card20; }

::view-transition-group(card1),
::view-transition-group(card2),
::view-transition-group(card3),
::view-transition-group(card4),

::view-transition-group(card20) {
    animation-timing-function: var(--bounce);
}

क्या आपको 20 एलिमेंट मिल गए? आपको 20 सिलेक्टर लिखने होंगे. क्या आपको कोई नया एलिमेंट जोड़ना है? इसके बाद, आपको उस सिलेक्टर को भी बढ़ाना होगा जो ऐनिमेशन स्टाइल लागू करता है. इसे आसानी से बढ़ाया नहीं जा सकता.

view-transition-class का इस्तेमाल व्यू ट्रांज़िशन के छद्म-तत्वों में किया जा सकता है, ताकि एक ही स्टाइल के नियम को लागू किया जा सके.

#card1 { view-transition-name: card1; }
#card2 { view-transition-name: card2; }
#card3 { view-transition-name: card3; }
#card4 { view-transition-name: card4; }
#card5 { view-transition-name: card5; }

#card20 { view-transition-name: card20; }

#cards-wrapper > div {
  view-transition-class: card;
}
html::view-transition-group(.card) {
  animation-timing-function: var(--bounce);
}

कार्ड के इस उदाहरण में, पिछले सीएसएस स्निपेट का इस्तेमाल किया गया है. सभी कार्ड–जिनमें नए जोड़े गए कार्ड भी शामिल हैं–पर एक ही टाइमिंग लागू होती है. इसके लिए, एक ही सिलेक्टर: html::view-transition-group(.card) का इस्तेमाल किया जाता है.

कार्ड के डेमो की रिकॉर्डिंग. view-transition-class का इस्तेमाल करने पर, जोड़े गए या हटाए गए कार्ड को छोड़कर, सभी कार्ड पर एक जैसा animation-timing-function लागू होता है.

ट्रांज़िशन को डीबग करना

व्यू ट्रांज़िशन, सीएसएस ऐनिमेशन पर आधारित होते हैं. इसलिए, Chrome DevTools में मौजूद ऐनिमेशन पैनल, ट्रांज़िशन को डीबग करने के लिए बेहतरीन है.

ऐनिमेशन पैनल का इस्तेमाल करके, अगले ऐनिमेशन को रोका जा सकता है. इसके बाद, ऐनिमेशन को आगे-पीछे किया जा सकता है. इस दौरान, ट्रांज़िशन के छद्म-तत्वों को तत्व पैनल में देखा जा सकता है.

Chrome DevTools की मदद से व्यू ट्रांज़िशन को डीबग करना.

ट्रांज़िशन करने वाले एलिमेंट का एक ही डीओएम एलिमेंट होना ज़रूरी नहीं है

अब तक हमने हेडर और हेडर में मौजूद टेक्स्ट के लिए, अलग-अलग ट्रांज़िशन एलिमेंट बनाने के लिए view-transition-name का इस्तेमाल किया है. ये दोनों, DOM में बदलाव से पहले और बाद में एक ही एलिमेंट हैं. हालांकि, ऐसे ट्रांज़िशन बनाए जा सकते हैं जिनमें ऐसा नहीं होता.

उदाहरण के लिए, मुख्य वीडियो एम्बेड को view-transition-name दिया जा सकता है:

.full-embed {
  view-transition-name: full-embed;
}

इसके बाद, थंबनेल पर क्लिक करने पर, ट्रांज़िशन की अवधि के लिए इसे वही view-transition-name दिया जा सकता है:

thumbnail.onclick = async () => {
  thumbnail.style.viewTransitionName = 'full-embed';

  document.startViewTransition(() => {
    thumbnail.style.viewTransitionName = '';
    updateTheDOMSomehow();
  });
};

और नतीजा:

एक एलिमेंट से दूसरे एलिमेंट में ट्रांज़िशन हो रहा है. कम से कम डेमो. सोर्स.

अब थंबनेल, मुख्य इमेज में बदल जाता है. भले ही, ये दोनों एलिमेंट कॉन्सेप्ट के हिसाब से (और असल में) अलग-अलग हैं, लेकिन ट्रांज़िशन एपीआई इन्हें एक ही मानता है. ऐसा इसलिए, क्योंकि इनमें एक ही view-transition-name इस्तेमाल किया गया है.

इस ट्रांज़िशन के लिए इस्तेमाल किया गया असली कोड, ऊपर दिए गए उदाहरण से थोड़ा ज़्यादा जटिल है. ऐसा इसलिए, क्योंकि यह थंबनेल पेज पर वापस जाने के ट्रांज़िशन को भी मैनेज करता है. इसे पूरी तरह से लागू करने के लिए, सोर्स देखें.


ऑब्जेक्ट को सीन में शामिल करने और हटाने पर दिखने वाले कस्टम ट्रांज़िशन

इस उदाहरण पर एक नज़र डालें:

साइडबार में जाना और उससे बाहर निकलना. कम से कम डेमो. सोर्स.

साइडबार, ट्रांज़िशन का हिस्सा है:

.sidebar {
  view-transition-name: sidebar;
}

हालांकि, पिछले उदाहरण में दिए गए हेडर के उलट, साइडबार सभी पेजों पर नहीं दिखता. अगर दोनों स्थितियों में साइडबार मौजूद है, तो ट्रांज़िशन स्यूडो-एलिमेंट इस तरह दिखते हैं:

::view-transition
├─ …other transition groups…
└─ ::view-transition-group(sidebar)
   └─ ::view-transition-image-pair(sidebar)
      ├─ ::view-transition-old(sidebar)
      └─ ::view-transition-new(sidebar)

हालांकि, अगर साइडबार सिर्फ़ नए पेज पर है, तो ::view-transition-old(sidebar) छद्म-तत्व मौजूद नहीं होगा. साइडबार के लिए कोई 'पुरानी' इमेज नहीं है. इसलिए, इमेज-पेयर में सिर्फ़ ::view-transition-new(sidebar) होगा. इसी तरह, अगर साइडबार सिर्फ़ पुराने पेज पर है, तो इमेज-पेयर में सिर्फ़ ::view-transition-old(sidebar) होगा.

पिछले डेमो में, साइडबार के ट्रांज़िशन अलग-अलग हैं. यह इस बात पर निर्भर करता है कि साइडबार दिख रहा है, नहीं दिख रहा है या दोनों स्थितियों में मौजूद है. यह दाईं ओर से स्लाइड होकर आता है और फ़ेड इन होता है. यह दाईं ओर स्लाइड होकर जाता है और फ़ेड आउट होता है. जब यह दोनों स्थितियों में मौजूद होता है, तब यह अपनी जगह पर बना रहता है.

खास एंट्री और एक्ज़िट ट्रांज़िशन बनाने के लिए, :only-child छद्म क्लास का इस्तेमाल किया जा सकता है. इससे इमेज-पेयर में मौजूद पुराने या नए छद्म-एलिमेंट को टारगेट किया जा सकता है. ऐसा तब किया जा सकता है, जब इमेज-पेयर में सिर्फ़ एक चाइल्ड मौजूद हो:

/* Entry transition */
::view-transition-new(sidebar):only-child {
  animation: 300ms cubic-bezier(0, 0, 0.2, 1) both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

/* Exit transition */
::view-transition-old(sidebar):only-child {
  animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}

इस मामले में, साइडबार के दोनों स्थितियों में मौजूद होने पर कोई खास ट्रांज़िशन नहीं होता, क्योंकि डिफ़ॉल्ट ट्रांज़िशन सही होता है.

एसिंक डीओएम अपडेट और कॉन्टेंट के लोड होने का इंतज़ार करना

.startViewTransition() को पास किया गया कॉलबैक, प्रॉमिस दिखा सकता है. इससे एसिंक डीओएम अपडेट किए जा सकते हैं. साथ ही, ज़रूरी कॉन्टेंट के तैयार होने का इंतज़ार किया जा सकता है.

document.startViewTransition(async () => {
  await something;
  await updateTheDOMSomehow();
  await somethingElse;
});

जब तक प्रॉमिस पूरा नहीं हो जाता, तब तक ट्रांज़िशन शुरू नहीं होगा. इस दौरान, पेज फ़्रीज़ हो जाता है. इसलिए, यहां कम से कम समय लगना चाहिए. खास तौर पर, नेटवर्क फ़ेच को .startViewTransition() को कॉल करने से पहले किया जाना चाहिए. ऐसा तब किया जाना चाहिए, जब पेज पूरी तरह से इंटरैक्टिव हो. इन्हें .startViewTransition() कॉलबैक के हिस्से के तौर पर नहीं किया जाना चाहिए.

अगर आपको इमेज या फ़ॉन्ट के तैयार होने का इंतज़ार करना है, तो पक्का करें कि आपने टाइम आउट की अवधि कम रखी हो:

const wait = ms => new Promise(r => setTimeout(r, ms));

document.startViewTransition(async () => {
  updateTheDOMSomehow();

  // Pause for up to 100ms for fonts to be ready:
  await Promise.race([document.fonts.ready, wait(100)]);
});

हालांकि, कुछ मामलों में देरी से बचना बेहतर होता है. ऐसे में, आपके पास मौजूद कॉन्टेंट का इस्तेमाल करें.


मौजूदा कॉन्टेंट का ज़्यादा से ज़्यादा फ़ायदा पाएं

अगर थंबनेल को बड़ी इमेज में बदल दिया जाता है, तो:

थंबनेल से बड़ी इमेज में ट्रांज़िशन हो रहा है. डेमो साइट आज़माएं.

डिफ़ॉल्ट ट्रांज़िशन क्रॉस-फ़ेड होता है. इसका मतलब है कि थंबनेल, अभी तक लोड नहीं हुई पूरी इमेज के साथ क्रॉस-फ़ेड हो सकता है.

इस समस्या को हल करने का एक तरीका यह है कि ट्रांज़िशन शुरू करने से पहले, पूरी इमेज लोड होने का इंतज़ार करें. आदर्श रूप से, यह काम .startViewTransition() को कॉल करने से पहले किया जाना चाहिए, ताकि पेज इंटरैक्टिव बना रहे. साथ ही, उपयोगकर्ता को यह बताने के लिए स्पिनर दिखाया जा सके कि चीज़ें लोड हो रही हैं. हालांकि, इस मामले में एक बेहतर तरीका है:

::view-transition-old(full-embed),
::view-transition-new(full-embed) {
  /* Prevent the default animation,
  so both views remain opacity:1 throughout the transition */
  animation: none;
  /* Use normal blending,
  so the new view sits on top and obscures the old view */
  mix-blend-mode: normal;
}

अब थंबनेल धुंधला नहीं होता, बल्कि पूरी इमेज के नीचे दिखता है. इसका मतलब है कि अगर नया व्यू लोड नहीं हुआ है, तो ट्रांज़िशन के दौरान थंबनेल दिखता रहेगा. इसका मतलब है कि ट्रांज़िशन तुरंत शुरू हो सकता है और पूरी इमेज अपने समय पर लोड हो सकती है.

अगर नए व्यू में पारदर्शिता की सुविधा मौजूद होती, तो यह काम नहीं करता. हालाँकि, इस मामले में हमें पता है कि ऐसा नहीं है. इसलिए, हम यह ऑप्टिमाइज़ेशन कर सकते हैं.

आसपेक्ट रेशियो में होने वाले बदलावों को हैंडल करना

अब तक, सभी ट्रांज़िशन एक ही आसपेक्ट रेशियो वाले एलिमेंट पर हुए हैं. हालांकि, ऐसा हमेशा नहीं होगा. अगर थंबनेल 1:1 और मुख्य इमेज 16:9 है, तो क्या होगा?

एक एलिमेंट से दूसरे एलिमेंट में ट्रांज़िशन हो रहा है. इस दौरान, आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) बदल रहा है. कम से कम डेमो. सोर्स.

डिफ़ॉल्ट ट्रांज़िशन में, ग्रुप को पहले के साइज़ से बाद के साइज़ में ऐनिमेट किया जाता है. पुराने और नए व्यू, ग्रुप की चौड़ाई के 100% होते हैं. साथ ही, इनकी ऊंचाई अपने-आप तय होती है. इसका मतलब है कि ग्रुप के साइज़ से इनके आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) पर कोई असर नहीं पड़ता.

यह एक अच्छा डिफ़ॉल्ट है, लेकिन इस मामले में यह काम का नहीं है. इसलिए:

::view-transition-old(full-embed),
::view-transition-new(full-embed) {
  /* Prevent the default animation,
  so both views remain opacity:1 throughout the transition */
  animation: none;
  /* Use normal blending,
  so the new view sits on top and obscures the old view */
  mix-blend-mode: normal;
  /* Make the height the same as the group,
  meaning the view size might not match its aspect-ratio. */
  height: 100%;
  /* Clip any overflow of the view */
  overflow: clip;
}

/* The old view is the thumbnail */
::view-transition-old(full-embed) {
  /* Maintain the aspect ratio of the view,
  by shrinking it to fit within the bounds of the element */
  object-fit: contain;
}

/* The new view is the full image */
::view-transition-new(full-embed) {
  /* Maintain the aspect ratio of the view,
  by growing it to cover the bounds of the element */
  object-fit: cover;
}

इसका मतलब है कि चौड़ाई बढ़ने पर थंबनेल, एलिमेंट के बीच में ही रहता है. हालांकि, 1:1 से 16:9 के आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) में बदलने पर, पूरी इमेज 'अन-क्रॉप' हो जाती है.

ज़्यादा जानकारी के लिए, व्यू ट्रांज़िशन: आसपेक्ट रेशियो में हुए बदलावों को मैनेज करना लेख पढ़ें


अलग-अलग डिवाइसों के लिए ट्रांज़िशन बदलने के लिए, मीडिया क्वेरी का इस्तेमाल करना

ऐसा हो सकता है कि आपको मोबाइल और डेस्कटॉप पर अलग-अलग ट्रांज़िशन इस्तेमाल करने हों. जैसे, इस उदाहरण में मोबाइल पर साइड से पूरी स्लाइड दिखती है, लेकिन डेस्कटॉप पर स्लाइड ज़्यादा साफ़ तौर पर दिखती है:

एक एलिमेंट से दूसरे एलिमेंट में ट्रांज़िशन हो रहा है. कम से कम डेमो. सोर्स.

इसे रेगुलर मीडिया क्वेरी का इस्तेमाल करके हासिल किया जा सकता है:

/* Transitions for mobile */
::view-transition-old(root) {
  animation: 300ms ease-out both full-slide-to-left;
}

::view-transition-new(root) {
  animation: 300ms ease-out both full-slide-from-right;
}

@media (min-width: 500px) {
  /* Overrides for larger displays.
  This is the shared axis transition from earlier in the article. */
  ::view-transition-old(root) {
    animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
      300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
  }

  ::view-transition-new(root) {
    animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
      300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
  }
}

मीडिया क्वेरी से मेल खाने के आधार पर, आपको यह भी बदलना पड़ सकता है कि किन एलिमेंट को view-transition-name असाइन किया गया है.


'हलचल कम करें' सेटिंग के हिसाब से काम करना

उपयोगकर्ता अपने ऑपरेटिंग सिस्टम के ज़रिए, कम मोशन वाली सेटिंग को प्राथमिकता दे सकते हैं. यह प्राथमिकता सीएसएस में दिखती है.

आपके पास इन उपयोगकर्ताओं के लिए, किसी भी ट्रांज़िशन को रोकने का विकल्प है:

@media (prefers-reduced-motion) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

हालांकि, 'हलचल कम करें' सेटिंग का मतलब यह नहीं है कि उपयोगकर्ता को कोई हलचल नहीं चाहिए. ऊपर दिए गए स्निपेट के बजाय, ज़्यादा बेहतर ऐनिमेशन चुना जा सकता है. हालांकि, ऐसा ऐनिमेशन चुनें जिससे अब भी एलिमेंट के बीच के संबंध और डेटा के फ़्लो के बारे में पता चले.


व्यू ट्रांज़िशन टाइप की मदद से, व्यू ट्रांज़िशन की कई स्टाइल मैनेज करना

Browser Support

  • Chrome: 125.
  • Edge: 125.
  • Firefox Technology Preview: supported.
  • Safari: 18.

Source

कभी-कभी, एक व्यू से दूसरे व्यू पर ट्रांज़िशन के लिए, खास तौर पर तैयार किया गया ट्रांज़िशन होना चाहिए. उदाहरण के लिए, पेज नंबर के क्रम में अगले या पिछले पेज पर जाते समय, आपको कॉन्टेंट को अलग-अलग दिशाओं में स्लाइड करना पड़ सकता है. ऐसा इस बात पर निर्भर करता है कि आप क्रम में किसी बड़े पेज पर जा रहे हैं या छोटे पेज पर.

पेज नंबर डालने की सुविधा के डेमो की रिकॉर्डिंग. यह इस बात पर निर्भर करता है कि आपको किस पेज पर जाना है. इसके हिसाब से, अलग-अलग ट्रांज़िशन का इस्तेमाल किया जाता है.

इसके लिए, व्यू ट्रांज़िशन टाइप का इस्तेमाल किया जा सकता है. इनकी मदद से, किसी ऐक्टिव व्यू ट्रांज़िशन को एक या उससे ज़्यादा टाइप असाइन किए जा सकते हैं. उदाहरण के लिए, पेजों को क्रम में लगाने की सुविधा में किसी अगले पेज पर जाने के लिए, forwards टाइप का इस्तेमाल करें. वहीं, किसी पिछले पेज पर जाने के लिए, backwards टाइप का इस्तेमाल करें. ये टाइप सिर्फ़ तब चालू होते हैं, जब ट्रांज़िशन को कैप्चर किया जा रहा हो या ट्रांज़िशन किया जा रहा हो. साथ ही, अलग-अलग ऐनिमेशन का इस्तेमाल करने के लिए, हर टाइप को सीएसएस के ज़रिए पसंद के मुताबिक बनाया जा सकता है.

एक ही दस्तावेज़ में व्यू ट्रांज़िशन के लिए टाइप का इस्तेमाल करने के लिए, startViewTransition तरीके में types पास करें. इसके लिए, document.startViewTransition एक ऑब्जेक्ट भी स्वीकार करता है: update, डीओएम को अपडेट करने वाला कॉलबैक फ़ंक्शन है. वहीं, types, टाइप वाला एक ऐरे है.

const direction = determineBackwardsOrForwards();

const t = document.startViewTransition({
  update: updateTheDOMSomehow,
  types: ['slide', direction],
});
का इस्तेमाल करें

इन सवालों के जवाब देने के लिए, :active-view-transition-type() चुनने वाले टूल का इस्तेमाल करें. टारगेट करने के लिए, type को सिलेक्टर में पास करें. इससे आपको एक से ज़्यादा व्यू ट्रांज़िशन की स्टाइल को एक-दूसरे से अलग रखने में मदद मिलती है. साथ ही, एक स्टाइल के एलान से दूसरी स्टाइल के एलान में कोई रुकावट नहीं आती.

टाइप सिर्फ़ ट्रांज़िशन को कैप्चर या पूरा करते समय लागू होते हैं. इसलिए, सिलेक्टर का इस्तेमाल करके, किसी एलिमेंट पर सिर्फ़ उस टाइप के व्यू ट्रांज़िशन के लिए view-transition-name को सेट या अनसेट किया जा सकता है.

/* 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 (using the default root snapshot) */
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;
  }
}

यहां दिए गए पेज नंबर डालने के डेमो में, पेज नंबर के हिसाब से पेज का कॉन्टेंट आगे या पीछे की ओर स्लाइड होता है. क्लिक के आधार पर टाइप तय किए जाते हैं. इसके बाद, उन्हें document.startViewTransition में पास कर दिया जाता है.

किसी भी तरह के ऐक्टिव व्यू ट्रांज़िशन को टारगेट करने के लिए, :active-view-transition छद्म-क्लास सिलेक्टर का इस्तेमाल किया जा सकता है.

html:active-view-transition {
    
}

व्यू ट्रांज़िशन रूट पर क्लास के नाम का इस्तेमाल करके, व्यू ट्रांज़िशन की कई स्टाइल मैनेज करना

कभी-कभी, एक तरह के व्यू से दूसरी तरह के व्यू पर ट्रांज़िशन करते समय, खास तौर पर तैयार किया गया ट्रांज़िशन होना चाहिए. इसके अलावा, 'बैक' नेविगेशन, 'फ़ॉरवर्ड' नेविगेशन से अलग होना चाहिए.

'वापस' जाने पर अलग-अलग ट्रांज़िशन. कम से कम डेमो. सोर्स.

ट्रांज़िशन टाइप से पहले, इन मामलों को मैनेज करने का तरीका यह था कि ट्रांज़िशन रूट पर कुछ समय के लिए क्लास का नाम सेट किया जाए. document.startViewTransition को कॉल करते समय, यह ट्रांज़िशन रूट <html> एलिमेंट होता है. इसे JavaScript में document.documentElement का इस्तेमाल करके ऐक्सेस किया जा सकता है:

if (isBackNavigation) {
  document.documentElement.classList.add('back-transition');
}

const transition = document.startViewTransition(() =>
  updateTheDOMSomehow(data)
);

try {
  await transition.finished;
} finally {
  document.documentElement.classList.remove('back-transition');
}

ट्रांज़िशन खत्म होने के बाद क्लास हटाने के लिए, इस उदाहरण में transition.finished का इस्तेमाल किया गया है. यह एक प्रॉमिस है, जो ट्रांज़िशन के आखिरी चरण में पहुंचने के बाद रिज़ॉल्व हो जाता है. इस ऑब्जेक्ट की अन्य प्रॉपर्टी के बारे में एपीआई के रेफ़रंस में बताया गया है.

अब ट्रांज़िशन बदलने के लिए, उस क्लास के नाम का इस्तेमाल अपनी सीएसएस में किया जा सकता है:

/* 'Forward' transitions */
::view-transition-old(root) {
  animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}

::view-transition-new(root) {
  animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, 300ms
      cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

/* Overrides for 'back' transitions */
.back-transition::view-transition-old(root) {
  animation-name: fade-out, slide-to-right;
}

.back-transition::view-transition-new(root) {
  animation-name: fade-in, slide-from-left;
}

मीडिया क्वेरी की तरह, इन क्लास की मौजूदगी का इस्तेमाल यह बदलने के लिए भी किया जा सकता है कि किन एलिमेंट को view-transition-name मिले.


अन्य ऐनिमेशन को रोके बिना ट्रांज़िशन चलाएं

वीडियो की पोज़िशन बदलने का यह डेमो देखें:

वीडियो ट्रांज़िशन. कम से कम डेमो. सोर्स.

क्या आपको इसमें कोई समस्या दिखी? अगर आपने ऐसा नहीं किया है, तो चिंता न करें. यहां इसे धीमी गति से दिखाया गया है:

वीडियो ट्रांज़िशन, धीमा. कम से कम डेमो. सोर्स.

ट्रांज़िशन के दौरान, वीडियो कुछ देर के लिए रुक जाता है. इसके बाद, वीडियो का चालू वर्शन दिखने लगता है. ऐसा इसलिए है, क्योंकि ::view-transition-old(video) पुराने व्यू का स्क्रीनशॉट है, जबकि ::view-transition-new(video) नए व्यू की लाइव इमेज है.

इस समस्या को ठीक किया जा सकता है. हालांकि, इससे पहले खुद से यह सवाल पूछें कि क्या इसे ठीक करना फ़ायदेमंद होगा. अगर ट्रांज़िशन को सामान्य स्पीड पर चलाने के दौरान आपको 'समस्या' नहीं दिखी, तो इसे बदलने की ज़रूरत नहीं है.

अगर आपको वाकई में इसे ठीक करना है, तो ::view-transition-old(video) न दिखाएं; सीधे ::view-transition-new(video) पर स्विच करें. डिफ़ॉल्ट स्टाइल और ऐनिमेशन को बदलकर ऐसा किया जा सकता है:

::view-transition-old(video) {
  /* Don't show the frozen old view */
  display: none;
}

::view-transition-new(video) {
  /* Don't fade the new view in */
  animation: none;
}

यह बहुत आसान है!

वीडियो ट्रांज़िशन, धीमा. कम से कम डेमो. सोर्स.

अब वीडियो, ट्रांज़िशन के दौरान चलता है.


Navigation API और अन्य फ़्रेमवर्क के साथ इंटिग्रेशन

व्यू ट्रांज़िशन को इस तरह से तय किया जाता है कि उन्हें अन्य फ़्रेमवर्क या लाइब्रेरी के साथ इंटिग्रेट किया जा सके. उदाहरण के लिए, अगर आपका सिंगल-पेज ऐप्लिकेशन (एसपीए) किसी राउटर का इस्तेमाल कर रहा है, तो व्यू ट्रांज़िशन का इस्तेमाल करके कॉन्टेंट को अपडेट करने के लिए, राउटर के अपडेट मैकेनिज़्म को अडजस्ट किया जा सकता है.

पेज नंबर डालने की सुविधा के इस डेमो से लिए गए कोड के इस स्निपेट में, Navigation API के इंटरसेप्शन हैंडलर को इस तरह से अडजस्ट किया गया है कि व्यू ट्रांज़िशन की सुविधा उपलब्ध होने पर, document.startViewTransition को कॉल किया जा सके.

navigation.addEventListener("navigate", (e) => {
    // Don't intercept if not needed
    if (shouldNotIntercept(e)) return;

    // Intercept the navigation
    e.intercept({
        handler: async () => {
            // Fetch the new content
            const newContent = await fetchNewContent(e.destination.url, {
                signal: e.signal,
            });

            // The UA does not support View Transitions, or the UA
            // already provided a Visual Transition by itself (e.g. swipe back).
            // In either case, update the DOM directly
            if (!document.startViewTransition || e.hasUAVisualTransition) {
                setContent(newContent);
                return;
            }

            // Update the content using a View Transition
            const t = document.startViewTransition(() => {
                setContent(newContent);
            });
        }
    });
});

कुछ ब्राउज़र, उपयोगकर्ता के स्वाइप करने पर ट्रांज़िशन की सुविधा देते हैं. हालांकि, सभी ब्राउज़र यह सुविधा नहीं देते. ऐसे में, आपको अपना व्यू ट्रांज़िशन ट्रिगर नहीं करना चाहिए. इससे लोगों को खराब अनुभव मिलेगा या वे भ्रमित हो जाएंगे. उपयोगकर्ता को दो ट्रांज़िशन दिखेंगे. एक ट्रांज़िशन ब्राउज़र से मिलेगा और दूसरा ट्रांज़िशन आपकी ओर से मिलेगा. ये दोनों ट्रांज़िशन एक के बाद एक दिखेंगे.

इसलिए, हमारा सुझाव है कि जब ब्राउज़र अपना विज़ुअल ट्रांज़िशन उपलब्ध कराता है, तब व्यू ट्रांज़िशन को शुरू होने से रोका जाए. इसके लिए, NavigateEvent इंस्टेंस की hasUAVisualTransition प्रॉपर्टी की वैल्यू देखें. जब ब्राउज़र विज़ुअल ट्रांज़िशन उपलब्ध कराता है, तब प्रॉपर्टी को true पर सेट किया जाता है. यह hasUIVisualTransition प्रॉपर्टी, PopStateEvent इंस्टेंस पर भी मौजूद होती है.

पिछले स्निपेट में, यह जांच की जाती है कि व्यू ट्रांज़िशन को चलाना है या नहीं. इसके लिए, इस प्रॉपर्टी को ध्यान में रखा जाता है. जब एक ही दस्तावेज़ में व्यू ट्रांज़िशन की सुविधा काम नहीं करती है या ब्राउज़र पहले से ही अपना ट्रांज़िशन उपलब्ध कराता है, तो व्यू ट्रांज़िशन को स्किप कर दिया जाता है.

if (!document.startViewTransition || e.hasUAVisualTransition) {
  setContent(newContent);
  return;
}

इस रिकॉर्डिंग में, उपयोगकर्ता पिछले पेज पर वापस जाने के लिए स्वाइप करता है. बाईं ओर दिए गए कैप्चर में, hasUAVisualTransition फ़्लैग की जांच शामिल नहीं है. दाईं ओर की रिकॉर्डिंग में चेक शामिल है. इसलिए, मैन्युअल व्यू ट्रांज़िशन को स्किप कर दिया गया है, क्योंकि ब्राउज़र ने विज़ुअल ट्रांज़िशन उपलब्ध कराया है.

एक ही साइट की तुलना. बाईं ओर, hasUAVisualTransition की जांच किए बिना और दाईं ओर, hasUAVisualTransition की जांच करने के बाद की तुलना दिखाई गई है

JavaScript की मदद से ऐनिमेशन बनाना

अब तक, सभी ट्रांज़िशन को सीएसएस का इस्तेमाल करके तय किया गया है. हालांकि, कभी-कभी सीएसएस काफ़ी नहीं होती:

सर्कल ट्रांज़िशन. कम से कम डेमो. सोर्स.

इस ट्रांज़िशन के कुछ हिस्सों को सिर्फ़ सीएसएस की मदद से नहीं बनाया जा सकता:

  • ऐनिमेशन, क्लिक की गई जगह से शुरू होता है.
  • ऐनिमेशन में, सर्कल का दायरा सबसे दूर वाले कोने तक बढ़ता हुआ दिखता है. हालांकि, हमें उम्मीद है कि आने वाले समय में सीएसएस के साथ ऐसा किया जा सकेगा.

अच्छी बात यह है कि Web Animation API का इस्तेमाल करके ट्रांज़िशन बनाए जा सकते हैं!

let lastClick;
addEventListener('click', event => (lastClick = event));

function spaNavigate(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // Get the click position, or fallback to the middle of the screen
  const x = lastClick?.clientX ?? innerWidth / 2;
  const y = lastClick?.clientY ?? innerHeight / 2;
  // Get the distance to the furthest corner
  const endRadius = Math.hypot(
    Math.max(x, innerWidth - x),
    Math.max(y, innerHeight - y)
  );

  // With a transition:
  const transition = document.startViewTransition(() => {
    updateTheDOMSomehow(data);
  });

  // Wait for the pseudo-elements to be created:
  transition.ready.then(() => {
    // Animate the root's new view
    document.documentElement.animate(
      {
        clipPath: [
          `circle(0 at ${x}px ${y}px)`,
          `circle(${endRadius}px at ${x}px ${y}px)`,
        ],
      },
      {
        duration: 500,
        easing: 'ease-in',
        // Specify which pseudo-element to animate
        pseudoElement: '::view-transition-new(root)',
      }
    );
  });
}

इस उदाहरण में, transition.ready का इस्तेमाल किया गया है. यह एक प्रॉमिस है, जो ट्रांज़िशन के छद्म एलिमेंट के बन जाने के बाद रिज़ॉल्व हो जाता है. इस ऑब्जेक्ट की अन्य प्रॉपर्टी के बारे में एपीआई के रेफ़रंस में बताया गया है.


ट्रांज़िशन को बेहतर बनाने की सुविधा

View Transition API को DOM में किए गए बदलाव को 'रैप' करने और उसके लिए ट्रांज़िशन बनाने के लिए डिज़ाइन किया गया है. हालांकि, ट्रांज़िशन को बेहतर बनाने के तौर पर देखा जाना चाहिए. इसका मतलब है कि अगर DOM में बदलाव हो जाता है, लेकिन ट्रांज़िशन पूरा नहीं होता है, तो आपके ऐप्लिकेशन को 'गड़बड़ी' वाली स्थिति में नहीं जाना चाहिए. आदर्श रूप से, ट्रांज़िशन में कोई गड़बड़ी नहीं होनी चाहिए. हालांकि, अगर ऐसा होता है, तो इससे उपयोगकर्ता अनुभव पर कोई असर नहीं पड़ना चाहिए.

ट्रांज़िशन को बेहतर बनाने के लिए, ट्रांज़िशन प्रॉमिस का इस्तेमाल इस तरह से न करें कि ट्रांज़िशन पूरा न होने पर, आपका ऐप्लिकेशन बंद हो जाए.

यह न करें
async function switchView(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    await updateTheDOM(data);
    return;
  }

  const transition = document.startViewTransition(async () => {
    await updateTheDOM(data);
  });

  await transition.ready;

  document.documentElement.animate(
    {
      clipPath: [`inset(50%)`, `inset(0)`],
    },
    {
      duration: 500,
      easing: 'ease-in',
      pseudoElement: '::view-transition-new(root)',
    }
  );
}

इस उदाहरण में समस्या यह है कि अगर ट्रांज़िशन switchView() स्थिति तक नहीं पहुंच पाता है, तो switchView() अस्वीकार कर देगा. हालांकि, इसका मतलब यह नहीं है कि व्यू स्विच नहीं हुआ.ready ऐसा हो सकता है कि DOM अपडेट हो गया हो, लेकिन डुप्लीकेट view-transition-name मौजूद थे. इसलिए, ट्रांज़िशन को छोड़ दिया गया.

इसके बजाय:

यह करें
async function switchView(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    await updateTheDOM(data);
    return;
  }

  const transition = document.startViewTransition(async () => {
    await updateTheDOM(data);
  });

  animateFromMiddle(transition);

  await transition.updateCallbackDone;
}

async function animateFromMiddle(transition) {
  try {
    await transition.ready;

    document.documentElement.animate(
      {
        clipPath: [`inset(50%)`, `inset(0)`],
      },
      {
        duration: 500,
        easing: 'ease-in',
        pseudoElement: '::view-transition-new(root)',
      }
    );
  } catch (err) {
    // You might want to log this error, but it shouldn't break the app
  }
}

इस उदाहरण में, DOM अपडेट होने का इंतज़ार करने के लिए transition.updateCallbackDone का इस्तेमाल किया गया है. साथ ही, अपडेट न होने पर उसे अस्वीकार करने के लिए भी इसका इस्तेमाल किया गया है. switchView अब ट्रांज़िशन पूरा न होने पर, उसे अस्वीकार नहीं करता है. यह DOM अपडेट पूरा होने पर हल हो जाता है. अगर यह पूरा नहीं होता है, तो इसे अस्वीकार कर दिया जाता है.

अगर आपको switchView को तब हल करना है, जब नया व्यू 'सेट हो गया हो', जैसे कि कोई ऐनिमेशन वाला ट्रांज़िशन पूरा हो गया हो या आखिर तक स्किप कर दिया गया हो, तो transition.updateCallbackDone को transition.finished से बदलें.


यह पॉलीफ़िल नहीं है, लेकिन…

इस सुविधा को पॉलीफ़िल करना आसान नहीं है. हालांकि, यह हेल्पर फ़ंक्शन उन ब्राउज़र में चीज़ों को बहुत आसान बना देता है जिनमें व्यू ट्रांज़िशन की सुविधा काम नहीं करती:

function transitionHelper({
  skipTransition = false,
  types = [],
  update,
}) {

  const unsupported = (error) => {
    const updateCallbackDone = Promise.resolve(update()).then(() => {});

    return {
      ready: Promise.reject(Error(error)),
      updateCallbackDone,
      finished: updateCallbackDone,
      skipTransition: () => {},
      types,
    };
  }

  if (skipTransition || !document.startViewTransition) {
    return unsupported('View Transitions are not supported in this browser');
  }

  try {
    const transition = document.startViewTransition({
      update,
      types,
    });

    return transition;
  } catch (e) {
    return unsupported('View Transitions with types are not supported in this browser');
  }
}

इसका इस्तेमाल इस तरह किया जा सकता है:

function spaNavigate(data) {
  const types = isBackNavigation ? ['back-transition'] : [];

  const transition = transitionHelper({
    update() {
      updateTheDOMSomehow(data);
    },
    types,
  });

  // …
}

जिन ब्राउज़र पर व्यू ट्रांज़िशन काम नहीं करते हैं उनमें updateDOM को अब भी कॉल किया जाएगा. हालांकि, ऐनिमेशन वाला ट्रांज़िशन नहीं होगा.

ट्रांज़िशन के दौरान, <html> में जोड़ने के लिए कुछ classNames भी दिए जा सकते हैं. इससे नेविगेशन के टाइप के हिसाब से ट्रांज़िशन को बदलना आसान हो जाता है.

अगर आपको ऐनिमेशन नहीं चाहिए, तो true को skipTransition पर भी पास किया जा सकता है. ऐसा उन ब्राउज़र में भी किया जा सकता है जिनमें व्यू ट्रांज़िशन की सुविधा काम करती है. अगर आपकी साइट पर उपयोगकर्ता के पास ट्रांज़िशन बंद करने का विकल्प है, तो यह तरीका काम का है.


फ़्रेमवर्क के साथ काम करना

अगर किसी ऐसी लाइब्रेरी या फ़्रेमवर्क का इस्तेमाल किया जा रहा है जो डीओएम में हुए बदलावों को छिपाता है, तो यह जानना मुश्किल हो जाता है कि डीओएम में बदलाव कब पूरा हुआ. यहां अलग-अलग फ़्रेमवर्क में, ऊपर दिए गए हेल्पर का इस्तेमाल करके बनाए गए उदाहरणों का सेट दिया गया है.

  • React—यहां मुख्य बात flushSync है, जो स्टेट में बदलावों के सेट को एक साथ लागू करता है. हां, उस एपीआई का इस्तेमाल करने के बारे में एक बड़ी चेतावनी दी गई है, लेकिन डैन अब्रामोव ने मुझे भरोसा दिलाया है कि इस मामले में इसका इस्तेमाल करना सही है. React और एसिंक कोड के साथ हमेशा की तरह, startViewTransition से मिले अलग-अलग प्रॉमिस का इस्तेमाल करते समय, ध्यान रखें कि आपका कोड सही स्थिति में चल रहा हो.
  • Vue.js—यहां मुख्य बात nextTick है, जो DOM अपडेट होने के बाद पूरा होता है.
  • Svelte—यह Vue से काफ़ी मिलता-जुलता है. हालांकि, अगले बदलाव का इंतज़ार करने का तरीका tick है.
  • Lit—इसमें मुख्य बात यह है कि कॉम्पोनेंट में this.updateComplete का वादा किया जाता है. यह वादा तब पूरा होता है, जब डीओएम अपडेट हो जाता है.
  • Angular—यहां मुख्य बात applicationRef.tick है, जो डीओएम में किए गए बदलावों को फ़्लश करता है. Angular 17 वर्शन से, @angular/router के साथ मिलने वाले withViewTransitions का इस्तेमाल किया जा सकता है.

एपीआई का संदर्भ

const viewTransition = document.startViewTransition(update)

नई ViewTransition शुरू करें.

update एक ऐसा फ़ंक्शन है जिसे दस्तावेज़ की मौजूदा स्थिति कैप्चर होने के बाद कॉल किया जाता है.

इसके बाद, जब updateCallback से मिला प्रॉमिस पूरा हो जाता है, तो ट्रांज़िशन अगले फ़्रेम में शुरू हो जाता है. अगर updateCallback से मिला प्रॉमिस अस्वीकार कर दिया जाता है, तो ट्रांज़िशन बंद हो जाता है.

const viewTransition = document.startViewTransition({ update, types })

बताए गए टाइप के साथ नया ViewTransition शुरू करें

update को तब कॉल किया जाता है, जब दस्तावेज़ की मौजूदा स्थिति कैप्चर हो जाती है.

types ट्रांज़िशन को कैप्चर करते या उसे लागू करते समय, ट्रांज़िशन के ऐक्टिव टाइप सेट करता है. शुरुआत में यह खाली होता है. ज़्यादा जानकारी के लिए, नीचे viewTransition.types देखें.

ViewTransition के इंस्टेंस सदस्य:

viewTransition.updateCallbackDone

यह एक प्रॉमिस है. जब updateCallback से मिला प्रॉमिस पूरा हो जाता है, तब यह प्रॉमिस भी पूरा हो जाता है. अगर updateCallback से मिला प्रॉमिस अस्वीकार कर दिया जाता है, तो यह प्रॉमिस भी अस्वीकार कर दिया जाता है.

View Transition API, DOM में हुए बदलाव को रैप करता है और ट्रांज़िशन बनाता है. हालांकि, कभी-कभी आपको ट्रांज़िशन ऐनिमेशन के सफल या असफल होने से कोई फ़र्क़ नहीं पड़ता. आपको बस यह जानना होता है कि DOM में बदलाव कब हुआ. updateCallbackDone का इस्तेमाल उस मामले के लिए किया जाता है.

viewTransition.ready

यह एक ऐसा प्रॉमिस है जो ट्रांज़िशन के लिए छद्म-तत्व बनाए जाने और ऐनिमेशन शुरू होने पर पूरा होता है.

अगर ट्रांज़िशन शुरू नहीं किया जा सकता, तो यह अस्वीकार कर देता है. ऐसा गलत कॉन्फ़िगरेशन की वजह से हो सकता है. जैसे, डुप्लीकेट view-transition-name या updateCallback से अस्वीकार किया गया प्रॉमिस.

यह JavaScript की मदद से ट्रांज़िशन स्यूडो-एलिमेंट में ऐनिमेशन जोड़ने के लिए काम का है.

viewTransition.finished

यह एक प्रॉमिस है. यह तब पूरा होता है, जब आखिरी स्थिति उपयोगकर्ता को पूरी तरह से दिख जाती है और वह उससे इंटरैक्ट कर पाता है.

यह सिर्फ़ तब अस्वीकार करता है, जब updateCallback अस्वीकार किया गया प्रॉमिस दिखाता है. इससे पता चलता है कि एंड स्टेट नहीं बनाया गया है.

इसके अलावा, अगर ट्रांज़िशन शुरू नहीं होता है या ट्रांज़िशन के दौरान इसे छोड़ दिया जाता है, तो भी आखिरी स्थिति तक पहुंचा जा सकता है. इसलिए, finished पूरा हो जाता है.

viewTransition.types

यह Set-like ऑब्जेक्ट है, जिसमें ऐक्टिव व्यू ट्रांज़िशन के टाइप होते हैं. एंट्री में बदलाव करने के लिए, इसके इंस्टेंस के तरीके clear(), add(), और delete() का इस्तेमाल करें.

सीएसएस में किसी खास टाइप का जवाब देने के लिए, ट्रांज़िशन रूट पर :active-view-transition-type(type) स्यूडो-क्लास सिलेक्टर का इस्तेमाल करें.

व्यू ट्रांज़िशन खत्म होने पर, टाइप अपने-आप हट जाते हैं.

viewTransition.skipTransition()

ट्रांज़िशन के ऐनिमेशन वाले हिस्से को स्किप करें.

इससे updateCallback को कॉल करने की प्रोसेस नहीं रुकेगी, क्योंकि DOM में बदलाव, ट्रांज़िशन से अलग होता है.


डिफ़ॉल्ट स्टाइल और ट्रांज़िशन का रेफ़रंस

::view-transition
यह रूट स्यूडो-एलिमेंट है, जो व्यूपोर्ट को भरता है और इसमें हर ::view-transition-group शामिल होता है.
::view-transition-group

ऐब्सलूट पोज़िशनिंग.

'पहले' और 'बाद' की स्थितियों के बीच width और height ट्रांज़िशन करता है.

'पहले' और 'बाद' वाले व्यूपोर्ट-स्पेस क्वाड के बीच transform ट्रांज़िशन.

::view-transition-image-pair

ग्रुप को भरने के लिए, इसे पूरी तरह से पोज़िशन किया गया है.

isolation: isolate से पुराने और नए व्यू पर mix-blend-mode का असर कम होता है.

::view-transition-new और ::view-transition-old

इसे रैपर के सबसे ऊपर बाईं ओर रखा गया है.

यह ग्रुप की पूरी चौड़ाई में दिखता है, लेकिन इसकी ऊंचाई अपने-आप तय होती है. इसलिए, यह ग्रुप की पूरी जगह में दिखने के बजाय, अपने आसपेक्ट रेशियो को बनाए रखेगा.

इसमें mix-blend-mode: plus-lighter होना चाहिए, ताकि क्रॉस-फ़ेड सही तरीके से हो सके.

पुराना वर्शन opacity: 1 से opacity: 0 में बदल जाता है. नया व्यू, opacity: 0 से opacity: 1 में ट्रांज़िशन करता है.


सुझाव/राय दें या शिकायत करें

डेवलपर के सुझाव, शिकायत या राय का हमेशा स्वागत है. इसके लिए, GitHub पर CSS वर्किंग ग्रुप के साथ कोई समस्या दर्ज करें. इसमें अपने सुझाव और सवाल शामिल करें. अपनी समस्या के आगे [css-view-transitions] जोड़ें.

अगर आपको कोई गड़बड़ी मिलती है, तो Chromium में गड़बड़ी की शिकायत करें.