चाहे आपको यह पसंद हो या न हो, पैरलॅक्स इफ़ेक्ट का इस्तेमाल आने वाले समय में भी किया जाएगा. इसका सही तरीके से इस्तेमाल करने पर, किसी वेब ऐप्लिकेशन को बेहतर बनाया जा सकता है. हालांकि, इसकी समस्या यह है कि पैरललक्स को बेहतर तरीके से लागू करना मुश्किल हो सकता है. इस लेख में, हम एक ऐसे समाधान के बारे में बात करेंगे जो बेहतर परफ़ॉर्म करता है और सभी ब्राउज़र पर काम करता है.
बहुत ज़्यादा शब्द हैं, पढ़ा नहीं गया
- पैरलॅक्स ऐनिमेशन बनाने के लिए, स्क्रोल इवेंट या
background-position
का इस्तेमाल न करें. - पैरलॅक्स इफ़ेक्ट को ज़्यादा सटीक बनाने के लिए, CSS 3D ट्रांसफ़ॉर्म का इस्तेमाल करें.
- मोबाइल Safari के लिए,
position: sticky
का इस्तेमाल करके पक्का करें कि पैरलॅक्स इफ़ेक्ट दिखे.
अगर आपको ड्रॉप-इन वाला समाधान चाहिए, तो यूज़र इंटरफ़ेस (यूआई) एलिमेंट के सैंपल के लिए GitHub का डेटा स्टोर पर जाएं और पैरलॅक्स हेल्पर JS पाएं! GitHub रिपॉज़िटरी में, पैरलॅक्स स्क्रोलर का लाइव डेमो देखा जा सकता है.
समस्या के पैरलॅक्स
सबसे पहले, पैरलॅक्स इफ़ेक्ट पाने के दो सामान्य तरीकों के बारे में जानें. साथ ही, यह भी जानें कि ये हमारे काम के क्यों नहीं हैं.
गलत: स्क्रोल इवेंट का इस्तेमाल करना
पैरलॅक्स इफ़ेक्ट की मुख्य ज़रूरी शर्त यह है कि यह स्क्रोल-कप्ल होना चाहिए. पेज की स्क्रोल पोज़िशन में होने वाले हर बदलाव के लिए, पैरलॅक्स इफ़ेक्ट वाले एलिमेंट की पोज़िशन अपडेट होनी चाहिए. यह सुनने में आसान लग सकता है, लेकिन आधुनिक ब्राउज़र का एक अहम तरीका यह है कि वे अलग-अलग क्रम में काम कर सकते हैं. हमारे मामले में, यह स्क्रॉल इवेंट पर लागू होता है. ज़्यादातर ब्राउज़र में स्क्रोल इवेंट, "बेहतरीन कोशिश" के तौर पर डिलीवर किए जाते हैं. हालांकि, इस बात की कोई गारंटी नहीं है कि ये स्क्रोल ऐनिमेशन के हर फ़्रेम पर डिलीवर होंगे!
इस अहम जानकारी से हमें पता चलता है कि हमें स्क्रॉल इवेंट के आधार पर एलिमेंट को मूव करने वाले, 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>
पर्सपेक्टिव के लिए स्केल अडजस्ट करना
चाइल्ड एलिमेंट को पीछे धकेलने पर, वह पर्सपेक्टिव वैल्यू के हिसाब से छोटा हो जाएगा. इस समीकरण का इस्तेमाल करके, यह कैलकुलेट किया जा सकता है कि इसे कितना बड़ा करना होगा: (पर्सपेक्टिव - दूरी) / पर्सपेक्टिव. हम चाहते हैं कि पैरलॅक्स एलिमेंट, पैरलॅक्स के साथ-साथ उसी साइज़ में दिखे जिस साइज़ में हमने उसे बनाया है. इसलिए, इसे इस तरह स्केल अप करना होगा, न कि उसे वैसे ही छोड़ना होगा.
ऊपर दिए गए कोड में, पर्सपेक्टिव 1px है और parallax-child
की Z दूरी -2px है. इसका मतलब है कि एलिमेंट को तीन गुना बड़ा करना होगा. यह वैल्यू, कोड में डाली गई वैल्यू है:
scale(3)
.
जिस कॉन्टेंट पर translateZ
वैल्यू लागू नहीं है उसके लिए, वैल्यू के तौर पर शून्य का इस्तेमाल किया जा सकता है. इसका मतलब है कि स्केल (पर्सपेक्टिव - 0) /
पर्सपेक्टिव है, जो 1 की वैल्यू पर नेट आउट होता है. इसका मतलब है कि इसे ऊपर या नीचे स्केल नहीं किया गया है. सच में, यह बहुत काम का है.
यह तरीका कैसे काम करता है
यह समझना ज़रूरी है कि यह सुविधा क्यों काम करती है, क्योंकि हम जल्द ही इस जानकारी का इस्तेमाल करने वाले हैं. स्क्रोलिंग एक तरह का ट्रांसफ़ॉर्मेशन है. इसलिए, इसे तेज़ किया जा सकता है. इसमें ज़्यादातर जीपीयू की मदद से लेयर को एक से दूसरी जगह ले जाना शामिल होता है. आम तौर पर, स्क्रोल करने पर स्क्रोल किए जा रहे एलिमेंट और उसके चाइल्ड एलिमेंट की तुलना 1:1 में की जाती है.
अगर किसी एलिमेंट को 300px
नीचे स्क्रोल किया जाता है, तो उसके चाइल्ड एलिमेंट को उतनी ही दूरी तक ऊपर ले जाया जाता है: 300px
.
हालांकि, स्क्रोलिंग एलिमेंट पर पर्सपेक्टिव वैल्यू लागू करने से, इस प्रोसेस में गड़बड़ी होती है. इससे स्क्रोल ट्रांसफ़ॉर्मेशन के आधार पर काम करने वाले मैट्रिक में बदलाव होता है.
अब 300 पिक्सल के स्क्रोल से, चाइल्ड एलिमेंट सिर्फ़ 150 पिक्सल तक मूव हो सकते हैं. यह इस बात पर निर्भर करता है कि आपने perspective
और translateZ
की कौनसी वैल्यू चुनी है. अगर किसी एलिमेंट की translateZ
वैल्यू 0 है, तो उसे 1:1 पर स्क्रोल किया जाएगा (जैसा कि पहले किया जाता था). हालांकि, पर्सपेक्टिव ऑरिजिन से दूर Z में पुश किए गए चाइल्ड को अलग दर से स्क्रोल किया जाएगा! कुल नतीजा: पैरलॅक्स मोशन. सबसे अहम बात यह है कि इसे ब्राउज़र की स्क्रोल मशीन के हिस्से के तौर पर अपने-आप मैनेज किया जाता है. इसका मतलब है कि scroll
इवेंट को सुनने या background-position
को बदलने की ज़रूरत नहीं है.
एक समस्या: मोबाइल 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;
}
हालांकि, मोबाइल 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);
}
इससे, मोबाइल 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 रेपो में देखा जा सकता है.
इसे आज़माएं और हमें बताएं कि आपको कैसा लगा.