पैरलैक्सिंग का इस्तेमाल अब आम हो गया है. इसका सही तरीके से इस्तेमाल करने पर, वेब ऐप्लिकेशन को बेहतर बनाया जा सकता है. हालांकि, समस्या यह है कि परफ़ॉर्मेंस को बेहतर बनाने के लिए, पैरलैक्सिंग को लागू करना मुश्किल हो सकता है. इस लेख में, हम एक ऐसे समाधान के बारे में बात करेंगे जो परफ़ॉर्म करने में बेहतर है. साथ ही, यह अलग-अलग ब्राउज़र पर भी काम करता है.

TL;DR
- पैरलैक्स ऐनिमेशन बनाने के लिए, स्क्रोल इवेंट या
background-position
का इस्तेमाल न करें. - ज़्यादा सटीक पैरलैक्स इफ़ेक्ट बनाने के लिए, CSS 3D ट्रांसफ़ॉर्म का इस्तेमाल करें.
- Mobile Safari के लिए,
position: sticky
का इस्तेमाल करें, ताकि यह पक्का किया जा सके कि पैरलैक्स इफ़ेक्ट लागू हो गया है.
अगर आपको ड्रॉप-इन समाधान चाहिए, तो यूआई एलिमेंट के सैंपल के GitHub repo पर जाएं और Parallax helper JS पाएं! GitHub repo में, पैरलैक्स स्क्रोलर का लाइव डेमो देखा जा सकता है.
पैरलैक्स इफ़ेक्ट से जुड़ी समस्याएं
सबसे पहले, आइए पैरलैक्स इफ़ेक्ट पाने के दो सामान्य तरीकों पर एक नज़र डालें. साथ ही, यह भी जानें कि ये तरीके हमारे मकसद के लिए सही क्यों नहीं हैं.
खराब तरीका: स्क्रोल इवेंट का इस्तेमाल करना
पैरलैक्सिंग की मुख्य शर्त यह है कि इसे स्क्रोल से जोड़ा जाना चाहिए. पेज की स्क्रोल पोज़िशन में हर बदलाव के लिए, पैरलैक्सिंग एलिमेंट की पोज़िशन अपडेट होनी चाहिए. यह सुनने में आसान लगता है, लेकिन आधुनिक ब्राउज़र की एक अहम सुविधा यह है कि वे एसिंक्रोनस तरीके से काम कर सकते हैं. हमारे खास मामले में, यह स्क्रोल इवेंट पर लागू होता है. ज़्यादातर ब्राउज़र में स्क्रोल इवेंट, "बेस्ट-एफ़र्ट" के तौर पर डिलीवर किए जाते हैं. साथ ही, इस बात की कोई गारंटी नहीं होती कि स्क्रोल ऐनिमेशन के हर फ़्रेम पर इन्हें डिलीवर किया जाएगा!
इस अहम जानकारी से हमें पता चलता है कि हमें स्क्रोल इवेंट के आधार पर एलिमेंट को मूव करने वाले JavaScript-आधारित समाधान का इस्तेमाल क्यों नहीं करना चाहिए: JavaScript इस बात की गारंटी नहीं देता कि पैरलैक्सिंग, पेज की स्क्रोल पोज़िशन के साथ सिंक रहेगी. Mobile Safari के पुराने वर्शन में, स्क्रोल इवेंट को स्क्रोल के आखिर में डिलीवर किया जाता था. इस वजह से, JavaScript पर आधारित स्क्रोल इफ़ेक्ट बनाना मुमकिन नहीं था. नए वर्शन में, ऐनिमेशन के दौरान स्क्रोल इवेंट होते हैं. हालांकि, Chrome की तरह ही, यह "बेस्ट-एफ़र्ट" के आधार पर होता है. अगर मुख्य थ्रेड किसी दूसरे काम में व्यस्त है, तो स्क्रोल इवेंट तुरंत डिलीवर नहीं होंगे. इसका मतलब है कि पैरलैक्स इफ़ेक्ट नहीं दिखेगा.
खराब: background-position
अपडेट किया जा रहा है
हम हर फ़्रेम पर पेंट करने से बचना चाहते हैं. कई समाधान, पैरलैक्स इफ़ेक्ट देने के लिए background-position
को बदलने की कोशिश करते हैं. इससे स्क्रोल करने पर, ब्राउज़र को पेज के उन हिस्सों को फिर से रेंडर करना पड़ता है जिन पर असर पड़ा है. साथ ही, इससे ऐनिमेशन में काफ़ी रुकावट आ सकती है.
अगर हमें पैरलैक्स मोशन का वादा पूरा करना है, तो हमें ऐसी चीज़ चाहिए जिसे ऐक्सलरेटेड प्रॉपर्टी के तौर पर लागू किया जा सके. फ़िलहाल, इसका मतलब है कि ट्रांसफ़ॉर्म और ओपैसिटी का इस्तेमाल किया जाए. साथ ही, यह स्क्रोल इवेंट पर निर्भर न हो.
3D में सीएसएस
स्कॉट केलम और कीथ क्लार्क, दोनों ने पैरलैक्स मोशन पाने के लिए सीएसएस 3D का इस्तेमाल करने के क्षेत्र में काफ़ी काम किया है. वे इस तकनीक का इस्तेमाल करते हैं:
overflow-y: scroll
(और शायदoverflow-x: hidden
) के साथ स्क्रोल करने के लिए, कॉन्टेंट शामिल करने वाला एलिमेंट सेट अप करें.- उसी एलिमेंट पर
perspective
वैल्यू लागू करें. साथ ही,perspective-origin
कोtop left
या0 0
पर सेट करें. - उस एलिमेंट के बच्चों पर Z में अनुवाद लागू करें और उन्हें वापस स्केल करें, ताकि स्क्रीन पर उनके साइज़ पर असर डाले बिना पैरलैक्स मोशन मिल सके.
इस तरीके के लिए सीएसएस ऐसी दिखती है:
.container {
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
perspective: 1px;
perspective-origin: 0 0;
}
.parallax-child {
transform-origin: 0 0;
transform: translateZ(-2px) scale(3);
}
यह इस तरह के एचटीएमएल स्निपेट का इस्तेमाल करता है:
<div class="container">
<div class="parallax-child"></div>
</div>
परस्पेक्टिव के लिए स्केल को अडजस्ट करना
चाइल्ड एलिमेंट को पीछे की ओर ले जाने पर, पर्सपेक्टिव वैल्यू के हिसाब से वह छोटा हो जाएगा. इस समीकरण का इस्तेमाल करके, यह कैलकुलेट किया जा सकता है कि इसे कितना बड़ा करना होगा: (perspective - distance) / perspective. हम चाहते हैं कि पैरलैक्सिंग एलिमेंट पैरलैक्स करे, लेकिन उसी साइज़ में दिखे जिसमें हमने उसे बनाया है. इसलिए, इसे इस तरह से बड़ा करना होगा.
ऊपर दिए गए कोड में, पर्सपेक्टिव 1 पिक्सल है और parallax-child
की Z दूरी -2 पिक्सल है. इसका मतलब है कि एलिमेंट को 3x तक बड़ा करना होगा. इसे कोड में प्लग की गई वैल्यू के तौर पर देखा जा सकता है:
scale(3)
.
जिस कॉन्टेंट पर translateZ
वैल्यू लागू नहीं की गई है उसके लिए, शून्य वैल्यू का इस्तेमाल किया जा सकता है. इसका मतलब है कि स्केल (perspective - 0) / perspective है, जो 1 के बराबर है. इसका मतलब है कि इसे न तो बढ़ाया गया है और न ही घटाया गया है. यह वाकई बहुत काम का है.
यह तरीका कैसे काम करता है
यह समझना ज़रूरी है कि यह तरीका क्यों काम करता है, क्योंकि हम जल्द ही इस जानकारी का इस्तेमाल करने वाले हैं. स्क्रोलिंग एक तरह का ट्रांसफ़ॉर्म है. इसलिए, इसे तेज़ी से किया जा सकता है. इसमें ज़्यादातर, जीपीयू की मदद से लेयर को इधर-उधर किया जाता है. सामान्य स्क्रोल में, पर्सपेक्टिव का कोई कॉन्सेप्ट नहीं होता. इसमें स्क्रोलिंग एलिमेंट और उसके चाइल्ड की तुलना करने पर, स्क्रोलिंग 1:1 के हिसाब से होती है.
अगर किसी एलिमेंट को 300px
नीचे की ओर स्क्रोल किया जाता है, तो उसके चाइल्ड एलिमेंट को भी उतनी ही दूरी तक ऊपर की ओर ट्रांसफ़ॉर्म किया जाता है: 300px
.
हालांकि, स्क्रोल करने वाले एलिमेंट पर पर्सपेक्टिव वैल्यू लागू करने से, इस प्रोसेस में गड़बड़ी होती है. इससे स्क्रोल ट्रांसफ़ॉर्म को आधार देने वाली मैट्रिक्स बदल जाती हैं.
अब 300 पिक्सल के स्क्रोल से, बच्चों को सिर्फ़ 150 पिक्सल तक ले जाया जा सकता है. यह इस बात पर निर्भर करता है कि आपने perspective
और translateZ
की कौनसी वैल्यू चुनी हैं. अगर किसी एलिमेंट की translateZ
वैल्यू 0 है, तो उसे 1:1 के हिसाब से स्क्रोल किया जाएगा. हालांकि, पर्सपेक्टिव ओरिजन से Z की ओर पुश किए गए चाइल्ड को अलग रेट से स्क्रोल किया जाएगा! नतीजा: पैरलैक्स मोशन. सबसे अहम बात यह है कि इसे ब्राउज़र की इंटरनल स्क्रोल मशीनरी के हिस्से के तौर पर अपने-आप मैनेज किया जाता है. इसका मतलब है कि scroll
इवेंट सुनने या background-position
बदलने की कोई ज़रूरत नहीं है.
समस्या: Mobile Safari
हर इफ़ेक्ट के कुछ नुकसान होते हैं. ट्रांसफ़ॉर्म के लिए एक अहम नुकसान यह है कि इससे चाइल्ड एलिमेंट में 3D इफ़ेक्ट बरकरार नहीं रहते. अगर पर्सपेक्टिव वाले एलिमेंट और उसके पैरैलैक्सिंग चिल्ड्रन के बीच, क्रम में एलिमेंट मौजूद हैं, तो 3D पर्सपेक्टिव "फ़्लैट" हो जाता है. इसका मतलब है कि इफ़ेक्ट हट जाता है.
<div class="container">
<div class="parallax-container">
<div class="parallax-child"></div>
</div>
</div>
ऊपर दिए गए एचटीएमएल में, .parallax-container
नया है. इससे perspective
की वैल्यू कम हो जाएगी और हमें पैरलैक्स इफ़ेक्ट नहीं मिलेगा. ज़्यादातर मामलों में, इसका समाधान बहुत आसान है: आपको एलिमेंट में transform-style: preserve-3d
जोड़ना होगा. इससे, ट्री में ऊपर की ओर लागू किए गए 3D इफ़ेक्ट (जैसे कि हमारी पर्सपेक्टिव वैल्यू) को आगे बढ़ाया जा सकेगा.
.parallax-container {
transform-style: preserve-3d;
}
हालांकि, Mobile Safari के मामले में, चीज़ें थोड़ी ज़्यादा जटिल हैं.
कंटेनर एलिमेंट पर overflow-y: scroll
लागू करने से, तकनीकी तौर पर काम हो जाता है. हालांकि, स्क्रोल करने वाले एलिमेंट को फ़्लिंग नहीं किया जा सकता. -webkit-overflow-scrolling: touch
को जोड़ने से समस्या हल हो जाएगी, लेकिन इससे perspective
भी फ़्लैट हो जाएगा और हमें कोई पैरलैक्सिंग नहीं मिलेगी.
प्रोग्रेसिव एन्हांसमेंट के हिसाब से, यह शायद कोई बड़ी समस्या नहीं है. अगर हम हर स्थिति में पैरलैक्स इफ़ेक्ट लागू नहीं कर सकते, तो भी हमारा ऐप्लिकेशन काम करेगा. हालांकि, कोई दूसरा तरीका ढूंढना बेहतर होगा.
position: sticky
ने की मदद!
दरअसल, position: sticky
के तौर पर कुछ मदद मिलती है. इसका इस्तेमाल, स्क्रोल करने के दौरान एलिमेंट को व्यूपोर्ट के सबसे ऊपर या दिए गए पैरंट एलिमेंट से "चिपकाए" रखने के लिए किया जाता है. ज़्यादातर स्पेसिफ़िकेशन की तरह, यह स्पेसिफ़िकेशन भी काफ़ी बड़ा है. हालांकि, इसमें एक काम की जानकारी भी शामिल है:
पहली नज़र में यह जानकारी बहुत अहम नहीं लग सकती. हालांकि, इस वाक्य में एक अहम बात बताई गई है. इसमें बताया गया है कि किसी एलिमेंट के स्टिकी होने का हिसाब कैसे लगाया जाता है: "ऑफ़सेट का हिसाब, स्क्रोलिंग बॉक्स वाले सबसे नज़दीकी पैरंट एलिमेंट के हिसाब से लगाया जाता है". दूसरे शब्दों में कहें, तो स्टिकी एलिमेंट को दूसरी जगह ले जाने की दूरी (ताकि वह किसी दूसरे एलिमेंट या व्यूपोर्ट से जुड़ा हुआ दिखे) का हिसाब, अन्य ट्रांसफ़ॉर्म लागू होने से पहले लगाया जाता है, न कि बाद में. इसका मतलब है कि स्क्रोलिंग के पिछले उदाहरण की तरह ही, अगर ऑफ़सेट की गिनती 300 पिक्सल पर की गई थी, तो पर्सपेक्टिव (या कोई अन्य ट्रांसफ़ॉर्म) का इस्तेमाल करके, उस 300 पिक्सल ऑफ़सेट वैल्यू में बदलाव करने का एक नया अवसर मिलता है. ऐसा तब किया जा सकता है, जब इसे किसी स्टिकी एलिमेंट पर लागू किया जाता है.
पैरलैक्सिंग एलिमेंट पर position: -webkit-sticky
लागू करके, हम -webkit-overflow-scrolling:
touch
के फ़्लैटनिंग इफ़ेक्ट को "उलट" सकते हैं. इससे यह पक्का होता है कि पैरलेक्सिंग एलिमेंट, स्क्रोलिंग बॉक्स वाले सबसे नज़दीकी पैरंट एलिमेंट को रेफ़रंस करता है. इस मामले में, यह .container
है. इसके बाद, .parallax-container
पहले की तरह ही perspective
वैल्यू लागू करता है. इससे स्क्रोल ऑफ़सेट बदल जाता है और पैरलैक्स इफ़ेक्ट बन जाता है.
<div class="container">
<div class="parallax-container">
<div class="parallax-child"></div>
</div>
</div>
.container {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.parallax-container {
perspective: 1px;
}
.parallax-child {
position: -webkit-sticky;
top: 0px;
transform: translate(-2px) scale(3);
}
इससे Mobile Safari के लिए, पैरलैक्स इफ़ेक्ट वापस आ जाता है. यह सभी के लिए अच्छी खबर है!
स्टिकी पोज़िशनिंग से जुड़ी चेतावनियां
हालांकि, यहां एक अंतर है: position: sticky
, पैरलैक्स के तरीके को बदलता है. स्टिक की गई पोज़िशनिंग, एलिमेंट को स्क्रोलिंग कंटेनर से चिपकाने की कोशिश करती है. वहीं, स्टिक न की गई पोज़िशनिंग ऐसा नहीं करती. इसका मतलब है कि स्टिकी एलिमेंट के साथ पैरलैक्स इफ़ेक्ट, स्टिकी एलिमेंट के बिना पैरलैक्स इफ़ेक्ट के उलट होता है:
position: sticky
के साथ, एलिमेंट z=0 के जितना करीब होगा वह उतना ही कम मूव करेगा.position: sticky
के बिना, एलिमेंट z=0 के जितना करीब होगा वह उतना ही ज़्यादा मूव करेगा.
अगर आपको यह जानकारी थोड़ी मुश्किल लग रही है, तो रॉबर्ट फ़्लैक का यह डेमो देखें. इसमें बताया गया है कि स्टिकी पोज़िशनिंग के साथ और इसके बिना, एलिमेंट अलग-अलग तरीके से कैसे काम करते हैं. इनके बीच का अंतर देखने के लिए, आपको Chrome Canary (लिखते समय इसका वर्शन 56 था) या Safari की ज़रूरत होगी.

रॉबर्ट फ़्लैक का डेमो, जिसमें दिखाया गया है कि position: sticky
का पैरलैक्स स्क्रोलिंग पर क्या असर पड़ता है.
अलग-अलग गड़बड़ियां और उन्हें ठीक करने के तरीके
हालांकि, किसी भी चीज़ की तरह इसमें भी कुछ कमियां हैं, जिन्हें ठीक करने की ज़रूरत है:
- स्टिक होने की सुविधा ठीक से काम नहीं कर रही है. Chrome में यह सुविधा अब भी लागू की जा रही है. Edge में यह सुविधा काम नहीं करती. वहीं, Firefox में स्टिक होने की सुविधा को पर्सपेक्टिव ट्रांसफ़ॉर्म के साथ इस्तेमाल करने पर, पेंटिंग से जुड़ी गड़बड़ियां होती हैं. ऐसे मामलों में, सिर्फ़
position: sticky
(-webkit-
प्रीफ़िक्स वाला वर्शन) जोड़ने के लिए थोड़ा कोड जोड़ना सही होता है. ऐसा सिर्फ़ तब किया जाता है, जब इसकी ज़रूरत हो. यह सिर्फ़ Mobile Safari के लिए है. - Edge में यह इफ़ेक्ट "सिर्फ़ काम नहीं करता". Edge, ओएस लेवल पर स्क्रोलिंग को मैनेज करने की कोशिश करता है. आम तौर पर, यह अच्छी बात है. हालांकि, इस मामले में यह स्क्रोल के दौरान पर्सपेक्टिव में होने वाले बदलावों का पता लगाने से रोकता है. इसे ठीक करने के लिए, फ़िक्स्ड पोज़िशन वाला एलिमेंट जोड़ा जा सकता है. ऐसा इसलिए, क्योंकि इससे Edge, ओएस के बाहर स्क्रोल करने के तरीके पर स्विच हो जाता है. साथ ही, यह पक्का करता है कि पर्सपेक्टिव में हुए बदलावों को ध्यान में रखा जाए.
- "पेज का कॉन्टेंट बहुत बड़ा हो गया है!" कई ब्राउज़र, पेज के कॉन्टेंट का साइज़ तय करते समय स्केल को ध्यान में रखते हैं. हालांकि, अफ़सोस की बात है कि Chrome और Safari, पर्सपेक्टिव को ध्यान में नहीं रखते. इसलिए, अगर किसी एलिमेंट पर 3x का स्केल लागू किया गया है, तो आपको स्क्रोल बार वगैरह दिख सकते हैं. भले ही,
perspective
लागू होने के बाद एलिमेंट 1x पर हो. इस समस्या को हल करने के लिए, नीचे दिए गए तरीके अपनाए जा सकते हैं: नीचे दाएं कोने से (transform-origin: bottom right
की मदद से) एलिमेंट को स्केल करें. इससे बड़े साइज़ के एलिमेंट, स्क्रोल की जा सकने वाली जगह के "नेगेटिव रीजन" (आम तौर पर, ऊपर बाएं कोने में) में बढ़ जाएंगे. स्क्रोल की जा सकने वाली जगहों में, नेगेटिव रीजन में मौजूद कॉन्टेंट को कभी भी देखा या स्क्रोल नहीं किया जा सकता.
नतीजा
सोच-समझकर इस्तेमाल करने पर, पैरलैक्सिंग एक दिलचस्प इफ़ेक्ट है. जैसा कि आप देख सकते हैं, इसे इस तरह से लागू किया जा सकता है कि यह बेहतर तरीके से काम करे, स्क्रोल करने के साथ-साथ चले, और अलग-अलग ब्राउज़र पर काम करे. इसमें कुछ गणितीय कैलकुलेशन की ज़रूरत होती है. साथ ही, मनमुताबिक नतीजे पाने के लिए, कुछ बॉयलरप्लेट कोड की ज़रूरत होती है. इसलिए, हमने एक छोटी हेल्पर लाइब्रेरी और सैंपल तैयार किया है. इसे हमारी यूज़र इंटरफ़ेस (यूआई) एलिमेंट के सैंपल वाली GitHub repo में देखा जा सकता है.
इसे आज़माएं और हमें बताएं कि यह आपके लिए कितना मददगार रहा.