चाहे आपको यह पसंद हो या न हो, पैरलॅक्स इफ़ेक्ट का इस्तेमाल आने वाले समय में भी किया जाएगा. इसका सही तरीके से इस्तेमाल करने पर, किसी वेब ऐप्लिकेशन को बेहतर बनाया जा सकता है. हालांकि, इसकी समस्या यह है कि पैरललक्स को बेहतर तरीके से लागू करना मुश्किल हो सकता है. इस लेख में, हम एक ऐसे समाधान के बारे में बात करेंगे जो बेहतर परफ़ॉर्म करता है और सभी ब्राउज़र पर काम करता है.
बहुत ज़्यादा शब्द हैं, पढ़ा नहीं गया
- पैरलॅक्स ऐनिमेशन बनाने के लिए, स्क्रोल इवेंट या
background-position
का इस्तेमाल न करें. - पैरलॅक्स इफ़ेक्ट को ज़्यादा सटीक बनाने के लिए, CSS 3D ट्रांसफ़ॉर्म का इस्तेमाल करें.
- मोबाइल Safari के लिए,
position: sticky
का इस्तेमाल करके पक्का करें कि पैरलॅक्स इफ़ेक्ट दिखे.
अगर आपको ड्रॉप-इन सलूशन चाहिए, तो यूज़र इंटरफ़ेस (यूआई) एलिमेंट के सैंपल GitHub रेपो पर जाएं और Parallax हेल्पर 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 रेपो में देखा जा सकता है.
खेलें और हमें बताएं कि आपका सफ़र कैसा रहा.