आज के समय में डिवाइसों की सुविधाएं बहुत अलग-अलग हैं. इनमें से एक सुविधा यह है कि स्क्रीन की पिक्सल डेंसिटी की बहुत अलग-अलग वैल्यू उपलब्ध हैं. कुछ डिवाइसों में बहुत ज़्यादा रिज़ॉल्यूशन वाले डिसप्ले होते हैं, जबकि कुछ डिवाइसों में ऐसा नहीं होता. ऐप्लिकेशन डेवलपर को अलग-अलग पिक्सल डेंसिटी के साथ काम करना पड़ता है, जो काफ़ी मुश्किल हो सकता है. मोबाइल वेब पर, कई वजहों से चुनौतियां बढ़ जाती हैं:
- अलग-अलग साइज़ या कॉन्फ़िगरेशन वाले कई तरह के डिवाइस.
- सीमित नेटवर्क बैंडविड्थ और बैटरी लाइफ़.
इमेज के मामले में, वेब ऐप्लिकेशन डेवलपर का लक्ष्य सबसे अच्छी क्वालिटी की इमेज को ज़्यादा से ज़्यादा असरदार तरीके से दिखाना होता है. इस लेख में, आज और आने वाले समय में ऐसा करने के लिए कुछ काम की तकनीकें बताई गई हैं.
अगर हो सके, तो इमेज का इस्तेमाल न करें
इस विषय पर बातचीत शुरू करने से पहले, यह याद रखें कि वेब पर कई ऐसी बेहतरीन टेक्नोलॉजी मौजूद हैं जो ज़्यादातर रिज़ॉल्यूशन और डीपीआई पर निर्भर नहीं करती हैं. खास तौर पर, टेक्स्ट, एसवीजी, और ज़्यादातर सीएसएस "बस काम करेगी", क्योंकि वेब की अपने-आप पिक्सल स्केलिंग करने की सुविधा (devicePixelRatio के ज़रिए) काम करती है.
हालांकि, हमेशा रेस्टर इमेज का इस्तेमाल नहीं किया जा सकता. उदाहरण के लिए, हो सकता है कि आपको ऐसी एसेट दी गई हों जिन्हें पूरी तरह से SVG/CSS में दोहराना काफ़ी मुश्किल हो या आपको किसी फ़ोटो से काम करना हो. इमेज को अपने-आप SVG में बदला जा सकता है. हालांकि, फ़ोटो को वेक्टर में बदलने का कोई मतलब नहीं है, क्योंकि स्केल किए गए वर्शन आम तौर पर अच्छे नहीं दिखते.
बैकग्राउंड
डिसप्ले डेंसिटी का बहुत छोटा इतिहास
शुरुआती दिनों में, कंप्यूटर डिसप्ले की पिक्सल डेंसिटी 72 या 96 डीपीआई (डॉट प्रति इंच) होती थी.
डिसप्ले की पिक्सल डेंसिटी में धीरे-धीरे सुधार हुआ है. इसकी वजह मुख्य रूप से मोबाइल के इस्तेमाल का उदाहरण है. इसमें उपयोगकर्ता आम तौर पर अपने फ़ोन को अपने चेहरे के करीब रखते हैं, जिससे पिक्सल ज़्यादा दिखते हैं. साल 2008 तक, 150 डीपीआई वाले फ़ोन आम हो गए थे. डिसप्ले की पिक्सल डेंसिटी बढ़ाने का रुझान जारी रहा. आज के नए फ़ोन में 300 डीपीआई वाले डिसप्ले (Apple के "रेटिना" ब्रैंड वाले) हैं.
हालांकि, सबसे बेहतर डिसप्ले वह होता है जिसमें पिक्सल पूरी तरह से न दिखें. फ़ोन के फ़ॉर्म फ़ैक्टर के लिए, हो सकता है कि मौजूदा जनरेशन के रेटिना/HiDPI डिसप्ले, इस आदर्श के करीब हों. हालांकि, Project Glass जैसे नए हार्डवेयर और पहने जाने वाले डिवाइसों की वजह से, पिक्सल डेंसिटी में बढ़ोतरी जारी रहेगी.
आम तौर पर, कम डेंसिटी वाली इमेज नई स्क्रीन पर वैसी ही दिखती हैं जैसी वे पुरानी स्क्रीन पर दिखती थीं. हालांकि, उपयोगकर्ताओं को हाई डेंसिटी वाली साफ़ इमेज देखने की आदत होती है. इसलिए, कम डेंसिटी वाली इमेज उन्हें खराब और पिक्सल वाली लगती हैं. यहां एक अनुमानित सिम्युलेशन दिया गया है, जिसमें दिखाया गया है कि 1x इमेज, 2x डिसप्ले पर कैसी दिखेगी. इसके उलट, दो गुना बड़ी इमेज काफ़ी अच्छी लग रही है.


वेब पर पिक्सल
जब वेब को डिज़ाइन किया गया था, तब 99% डिसप्ले 96 डीपीआई (या ऐसा दिखाए जाते थे) थे. साथ ही, इस मामले में बदलाव के लिए कुछ ही प्रावधान किए गए थे. स्क्रीन के साइज़ और डेंसिटी में काफ़ी अंतर होने की वजह से, हमें एक स्टैंडर्ड तरीका चाहिए था, ताकि अलग-अलग स्क्रीन डेंसिटी और डाइमेंशन पर इमेज अच्छी दिखें.
एचटीएमएल स्पेसिफ़िकेशन ने हाल ही में इस समस्या को हल किया है. इसके लिए, रेफ़रंस पिक्सल तय किया गया है. मैन्युफ़ैक्चरर, सीएसएस पिक्सल का साइज़ तय करने के लिए इसका इस्तेमाल करते हैं.
रेफ़रंस पिक्सल का इस्तेमाल करके, मैन्युफ़ैक्चरर डिवाइस के फ़िज़िकल पिक्सल का साइज़, स्टैंडर्ड या आदर्श पिक्सल के हिसाब से तय कर सकता है. इस अनुपात को डिवाइस पिक्सल का अनुपात कहा जाता है.
डिवाइस पिक्सल रेशियो का हिसाब लगाना
मान लें कि किसी स्मार्ट फ़ोन की स्क्रीन का फ़िज़िकल पिक्सल साइज़ 180 पिक्सल प्रति इंच (पीपीआई) है. डिवाइस पिक्सल के अनुपात का हिसाब लगाने के लिए, ये तीन चरण पूरे करें:
डिवाइस को जिस असल दूरी पर रखा गया है उसकी तुलना, रेफ़रंस पिक्सल की दूरी से करें.
स्पेसिफ़िकेशन के मुताबिक, 28 इंच के लिए हर इंच में 96 पिक्सल सही होते हैं. हालांकि, यह एक स्मार्ट फ़ोन है, इसलिए लोग इसे लैपटॉप की तुलना में अपने चेहरे के ज़्यादा करीब रखते हैं. मान लें कि यह दूरी 18 इंच है.
दी गई दूरी के लिए सही पिक्सल डेंसिटी पाने के लिए, दूरी के अनुपात को स्टैंडर्ड डेंसिटी (96ppi) से गुणा करें.
idealPixelDensity = (28/18) * 96 = 150 पिक्सल प्रति इंच (लगभग)
डिवाइस पिक्सल का अनुपात पाने के लिए, फ़िज़िकल पिक्सल डेंसिटी और आदर्श पिक्सल डेंसिटी का अनुपात लें.
devicePixelRatio
= 180/150 = 1.2

इसलिए, जब किसी ब्राउज़र को यह पता करना होता है कि किसी इमेज का साइज़, स्क्रीन पर सही या स्टैंडर्ड रिज़ॉल्यूशन के हिसाब से कैसे घटाया या बढ़ाया जाए, तो वह डिवाइस के पिक्सल रेशियो 1.2 का इस्तेमाल करता है. इसका मतलब है कि हर सही पिक्सल के लिए, इस डिवाइस में 1.2 फ़िज़िकल पिक्सल होते हैं. आदर्श (वेब स्पेसिफ़िकेशन के मुताबिक) और फ़िज़िकल (डिवाइस की स्क्रीन पर बिंदु) पिक्सल के बीच बदलाव करने का फ़ॉर्मूला यह है:
physicalPixels = window.devicePixelRatio * idealPixels
अब तक, डिवाइस वेंडर devicePixelRatios
(डीपीआर) को राउंड करते रहे हैं. Apple के iPhone और iPad में डीपीआर 1 होता है. वहीं, उनके Retina डिवाइसों में डीपीआर 2 होता है. सीएसएस स्पेसिफ़िकेशन के मुताबिक,
पिक्सल यूनिट, डिवाइस के उन पिक्सल की कुल संख्या को दिखाती है जो रेफ़रंस पिक्सल के सबसे करीब होते हैं.
राउंड रेशियो बेहतर हो सकते हैं, इसकी एक वजह यह है कि इनसे सब-पिक्सल आर्टफ़ैक्ट कम हो सकते हैं.
हालांकि, डिवाइस के लैंडस्केप की असल स्थिति बहुत अलग है. आम तौर पर, Android फ़ोन का डीपीआर 1.5 होता है. नेक्सस 7 टैबलेट का डीपीआर ~1.33 है. यह ऊपर बताए गए तरीके से निकाला गया है. आने वाले समय में, आपको अलग-अलग डीपीआर वाले ज़्यादा डिवाइस दिख सकते हैं. इसलिए, आपको कभी यह नहीं मानना चाहिए कि आपके क्लाइंट के डीपीआर, पूर्णांक होंगे.
HiDPI इमेज बनाने की तकनीकों के बारे में खास जानकारी
सबसे अच्छी क्वालिटी की इमेज को जल्द से जल्द दिखाने की समस्या को हल करने के लिए, कई तकनीकें उपलब्ध हैं. ये तकनीकें मुख्य रूप से दो कैटगरी में आती हैं:
- एक इमेज को ऑप्टिमाइज़ करना, और
- एक से ज़्यादा इमेज में से चुनने के लिए, ऑप्टिमाइज़ेशन की सुविधा.
एक इमेज वाले विज्ञापन: एक इमेज का इस्तेमाल करें, लेकिन उसमें कुछ नया करें. इन तरीकों का इस्तेमाल करने पर, आपको परफ़ॉर्मेंस में कमी का सामना करना पड़ सकता है. ऐसा इसलिए, क्योंकि आपको कम डीपीआई वाले पुराने डिवाइसों पर भी HiDPI इमेज डाउनलोड करनी होंगी. एक इमेज वाले मामले के लिए, यहां कुछ तरीके दिए गए हैं:
- ज़्यादा कंप्रेस की गई HiDPI इमेज
- इमेज का बेहतरीन फ़ॉर्मैट
- प्रोग्रेसिव इमेज फ़ॉर्मैट
एक से ज़्यादा इमेज इस्तेमाल करने के तरीके: एक से ज़्यादा इमेज का इस्तेमाल करें, लेकिन यह तय करने के लिए कोई बेहतर तरीका अपनाएं कि कौनसी इमेज लोड करनी है. इन तरीकों में, डेवलपर को एक ही एसेट के कई वर्शन बनाने पड़ते हैं. इसके बाद, उन्हें फ़ैसला लेने की रणनीति तय करनी पड़ती है. विकल्प यहां दिए गए हैं:
- JavaScript
- सर्वर साइड डिलीवरी
- सीएसएस मीडिया क्वेरी
- ब्राउज़र में पहले से मौजूद सुविधाएं (
image-set()
,<img srcset>
)
ज़्यादा कंप्रेस की गई HiDPI इमेज
किसी औसत वेबसाइट को डाउनलोड करने में, इमेज का 60% बैंडविड्थ खर्च होता है. सभी क्लाइंट को HiDPI इमेज दिखाकर, हम इस संख्या को बढ़ाएंगे. यह कितना बड़ा होगा?
मैंने कुछ टेस्ट किए, जिनसे 90, 50, और 20 की JPEG क्वालिटी के साथ 1x और 2x इमेज फ़्रैगमेंट जनरेट हुए. इन्हें जनरेट करने के लिए, मैंने शेल स्क्रिप्ट का इस्तेमाल किया है. इसमें ImageMagick का इस्तेमाल किया गया है:



इस छोटे और ग़ैर-वैज्ञानिक सैंपलिंग से पता चलता है कि बड़ी इमेज को कंप्रेस करने से, क्वालिटी और साइज़ के बीच अच्छा समझौता होता है. मेरी राय में, ज़्यादा कंप्रेस की गई 2x इमेज, बिना कंप्रेस की गई 1x इमेज के मुकाबले बेहतर दिखती है.
ज़ाहिर है, 2x डिवाइसों पर खराब क्वालिटी और ज़्यादा कॉम्प्रेस की गई इमेज दिखाना, अच्छी क्वालिटी की इमेज दिखाने से ज़्यादा खराब है. साथ ही, ऊपर बताए गए तरीके से इमेज दिखाने पर, इमेज क्वालिटी के लिए जुर्माना भी लगाया जाता है. अगर 90 इमेज की क्वालिटी की तुलना 20 इमेज की क्वालिटी से की जाती है, तो आपको इमेज की क्वालिटी में गिरावट दिखेगी और उसमें ग्रेन दिखने लगेंगे. ऐसा हो सकता है कि इन आर्टफ़ैक्ट को उन मामलों में स्वीकार न किया जाए जहां अच्छी क्वालिटी की इमेज ज़रूरी हों. उदाहरण के लिए, फ़ोटो व्यूअर ऐप्लिकेशन. इसके अलावा, ऐसा उन ऐप्लिकेशन डेवलपर के लिए भी हो सकता है जो क्वालिटी से समझौता नहीं करना चाहते.
ऊपर दी गई तुलना, पूरी तरह से कंप्रेस किए गए JPEG फ़ॉर्मैट में की गई है. यह ध्यान देने वाली बात है कि आम तौर पर इस्तेमाल किए जाने वाले इमेज फ़ॉर्मैट (JPEG, PNG, GIF) के बीच कई अंतर हैं. इन अंतरों के बारे में यहां बताया गया है…
Totally awesome image format
WebP एक शानदार इमेज फ़ॉर्मैट है. यह इमेज की क्वालिटी को बरकरार रखते हुए, उसे काफ़ी अच्छी तरह से कंप्रेस करता है. हालांकि, यह सुविधा अभी हर जगह लागू नहीं की गई है!
WebP की सुविधा काम करती है या नहीं, यह पता करने का एक तरीका है कि JavaScript काम कर रहा है या नहीं. data-uri की मदद से 1 पिक्सल वाली इमेज लोड करें. इसके बाद, लोड होने या गड़बड़ी वाले इवेंट के ट्रिगर होने का इंतज़ार करें. इसके बाद, पुष्टि करें कि साइज़ सही है. Modernizr में ऐसी सुविधा की पहचान करने वाली स्क्रिप्ट होती है, जो Modernizr.webp
के ज़रिए उपलब्ध होती है.
हालांकि, ऐसा करने का बेहतर तरीका यह है कि सीधे तौर पर सीएसएस में image() फ़ंक्शन का इस्तेमाल करें. इसलिए, अगर आपके पास WebP इमेज और JPEG फ़ॉलबैक है, तो यह लिखा जा सकता है:
#pic {
background: image("foo.webp", "foo.jpg");
}
इस तरीके में कुछ समस्याएं हैं. सबसे पहले, image()
को बड़े पैमाने पर लागू नहीं किया गया है. दूसरी बात, WebP कंप्रेशन की तुलना में JPEG का साइज़ बहुत ज़्यादा होता है. हालांकि, WebP गैलरी के आधार पर, WebP का साइज़ 30% कम होता है. इसलिए, ज़्यादा डीपीआई की समस्या को हल करने के लिए, सिर्फ़ WebP का इस्तेमाल करना काफ़ी नहीं है.
प्रोग्रेसिव इमेज फ़ॉर्मैट
JPEG 2000, प्रोग्रेसिव JPEG, प्रोग्रेसिव PNG, और GIF जैसे प्रोग्रेसिव इमेज फ़ॉर्मैट का फ़ायदा यह है कि इमेज पूरी तरह से लोड होने से पहले ही दिखने लगती है. हालांकि, इस फ़ायदे के बारे में कुछ लोगों का कहना है कि यह फ़ायदा नहीं है. हालांकि, इस बारे में अलग-अलग सबूत हैं, लेकिन हो सकता है कि इनकी वजह से साइज़ में कुछ बढ़ोतरी हो. जेफ़ एटवुड ने दावा किया है कि प्रोग्रेसिव मोड की वजह से, "PNG इमेज का साइज़ करीब 20% और JPEG और GIF इमेज का साइज़ करीब 10% बढ़ जाता है". हालांकि, Stoyan Stefanov ने दावा किया है कि ज़्यादातर मामलों में, बड़ी फ़ाइलों के लिए प्रोग्रेसिव मोड ज़्यादा असरदार होता है.
पहली नज़र में, प्रोग्रेसिव इमेज, सबसे अच्छी क्वालिटी की इमेज को जल्द से जल्द दिखाने के मामले में काफ़ी आशाजनक लगती हैं. इसका मकसद यह है कि जब ब्राउज़र को पता चल जाए कि ज़्यादा डेटा से इमेज की क्वालिटी नहीं बढ़ेगी, तो वह इमेज को डाउनलोड और डिकोड करना बंद कर सकता है. जैसे, फ़िडेलिटी में हुए सभी सुधार सब-पिक्सल के हैं.
कनेक्शन को बंद करना आसान होता है, लेकिन उन्हें फिर से चालू करना अक्सर महंगा पड़ता है. कई इमेज वाली साइट के लिए, सबसे असरदार तरीका यह है कि एक ही एचटीटीपी कनेक्शन को चालू रखा जाए और उसे ज़्यादा से ज़्यादा समय तक इस्तेमाल किया जाए. अगर एक इमेज डाउनलोड हो जाने की वजह से कनेक्शन जल्दी खत्म हो जाता है, तो ब्राउज़र को नया कनेक्शन बनाना पड़ता है. यह कनेक्शन, कम इंतज़ार वाले एनवायरमेंट में काफ़ी धीमा हो सकता है.
इस समस्या को हल करने के लिए, एचटीटीपी रेंज अनुरोध का इस्तेमाल किया जा सकता है. इससे ब्राउज़र, फ़ेच करने के लिए बाइट की रेंज तय कर सकते हैं. कोई स्मार्ट ब्राउज़र, हेडर को ऐक्सेस करने के लिए HEAD अनुरोध कर सकता है, उसे प्रोसेस कर सकता है, यह तय कर सकता है कि इमेज का कितना हिस्सा ज़रूरी है, और फिर उसे फ़ेच कर सकता है. माफ़ करें, वेब सर्वर पर एचटीटीपी रेंज का इस्तेमाल करना मुश्किल है. इसलिए, यह तरीका काम का नहीं है.
आखिर में, इस तरीके की एक साफ़ सी सीमा यह है कि आपके पास यह चुनने का विकल्प नहीं होता कि कौनसी इमेज लोड करनी है. सिर्फ़ एक ही इमेज की अलग-अलग फ़िडेलिटी को लोड किया जा सकता है. इस वजह से, "आर्ट डायरेक्शन" के इस्तेमाल के उदाहरण का समाधान नहीं होता.
JavaScript का इस्तेमाल करके यह तय करना कि कौनसी इमेज लोड करनी है
कौनसी इमेज लोड करनी है, यह तय करने का पहला और सबसे आसान तरीका यह है कि क्लाइंट में JavaScript का इस्तेमाल किया जाए. इस तरीके से, आपको अपने उपयोगकर्ता एजेंट के बारे में पूरी जानकारी मिलती है और सही कदम उठाने में मदद मिलती है. window.devicePixelRatio
की मदद से, डिवाइस के पिक्सल रेशियो का पता लगाया जा सकता है. साथ ही, स्क्रीन की चौड़ाई और ऊंचाई का पता लगाया जा सकता है. इसके अलावा, foresight.js लाइब्रेरी की तरह, नेविगेटर.कनेक्शन की मदद से नेटवर्क कनेक्शन की जानकारी हासिल की जा सकती है या झूठा अनुरोध किया जा सकता है. यह सारी जानकारी इकट्ठा करने के बाद, यह तय किया जा सकता है कि कौनसी इमेज लोड की जाए.
ऐसी एक मिलियन JavaScript लाइब्रेरी हैं जो ऊपर बताए गए काम करती हैं. हालांकि, अफ़सोस की बात है कि इनमें से कोई भी लाइब्रेरी खास तौर पर बेहतर नहीं है.
इस तरीके का एक बड़ा नुकसान यह है कि JavaScript का इस्तेमाल करने का मतलब है कि आपको इमेज लोड होने में तब तक देरी होगी, जब तक कि लुक-अहेड पार्सर काम करना बंद नहीं कर देता. इसका मतलब है कि pageload
इवेंट ट्रिगर होने तक, इमेज डाउनलोड भी नहीं होंगी. इस बारे में ज़्यादा जानने के लिए, जेसन ग्रिब्सबी के लेख को पढ़ें.
यह तय करना कि सर्वर पर कौनसी इमेज लोड करनी है
अपनी हर इमेज के लिए कस्टम अनुरोध हैंडलर लिखकर, यह फ़ैसला सर्वर-साइड पर छोड़ा जा सकता है. ऐसा हैंडलर, User-Agent के आधार पर Retina की सुविधा के काम करने की जांच करेगा. User-Agent, सर्वर को भेजी जाने वाली एकमात्र जानकारी होती है. इसके बाद, सर्वर-साइड लॉजिक के हिसाब से यह तय किया जाता है कि HiDPI ऐसेट दिखानी हैं या नहीं. इसके आधार पर, सही ऐसेट लोड की जाती है. ऐसेट का नाम, किसी जाने-पहचाने कन्वेंशन के हिसाब से रखा जाता है.
माफ़ करें, User-Agent ज़रूरी नहीं है कि इतनी जानकारी उपलब्ध कराए कि यह तय किया जा सके कि किसी डिवाइस को हाई या लो क्वालिटी की इमेज चाहिए या नहीं. साथ ही, यह बताने की ज़रूरत नहीं है कि User-Agent से जुड़ी कोई भी चीज़ हैक है और अगर हो सके, तो इससे बचना चाहिए.
सीएसएस मीडिया क्वेरी का इस्तेमाल करना
सीएसएस मीडिया क्वेरी, एलान करने वाली होती हैं. इनकी मदद से, अपनी ज़रूरत के हिसाब से ब्राउज़र को निर्देश दिए जा सकते हैं. मीडिया क्वेरी के सबसे सामान्य इस्तेमाल के अलावा, डिवाइस के साइज़ से मैच करने के लिए भी devicePixelRatio
का इस्तेमाल किया जा सकता है. इससे जुड़ी मीडिया क्वेरी, डिवाइस-पिक्सल-रेशियो है. इसमें कम से कम और ज़्यादा से ज़्यादा वैरिएंट भी शामिल हैं. अगर आपको हाई डीपीआई वाली इमेज लोड करनी हैं और डिवाइस का पिक्सल रेशियो थ्रेशोल्ड से ज़्यादा है, तो ये काम किए जा सकते हैं:
#my-image { background: (low.png); }
@media only screen and (min-device-pixel-ratio: 1.5) {
#my-image { background: (high.png); }
}
सभी वेंडर प्रीफ़िक्स के साथ, यह थोड़ा मुश्किल हो जाता है. ऐसा खास तौर पर, "min" और "max" प्रीफ़िक्स के प्लेसमेंट में अंतर की वजह से होता है:
@media only screen and (min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2),
(-webkit-min-device-pixel-ratio: 1.5),
(min-device-pixel-ratio: 1.5) {
#my-image {
background:url(high.png);
}
}
इस तरीके से, आपको पहले से पार्स करने की सुविधा के फ़ायदे फिर से मिल जाते हैं. यह सुविधा, JS सलूशन के साथ उपलब्ध नहीं थी. साथ ही, आपके पास रिस्पॉन्सिव ब्रेकपॉइंट चुनने का विकल्प भी होता है. उदाहरण के लिए, आपके पास कम, मध्यम, और ज़्यादा डीपीआई वाली इमेज हो सकती हैं. यह विकल्प, सर्वर-साइड वाले तरीके में नहीं था.
माफ़ करें, यह अब भी थोड़ा मुश्किल है और इससे अजीब दिखने वाली सीएसएस बनती है (या प्रीप्रोसेसिंग की ज़रूरत होती है). साथ ही, यह तरीका सिर्फ़ सीएसएस प्रॉपर्टी के लिए है. इसलिए, <img src>
सेट करने का कोई तरीका नहीं है. साथ ही, आपकी सभी इमेज, बैकग्राउंड वाले एलिमेंट होनी चाहिए. आखिर में, डिवाइस के पिक्सल रेशियो पर पूरी तरह से भरोसा करने पर, आपको ऐसी स्थितियां मिल सकती हैं जहां आपका हाई-डीपीआई स्मार्ट फ़ोन, EDGE कनेक्शन पर दो गुना बड़ी इमेज एसेट डाउनलोड कर लेता है. यह उपयोगकर्ताओं के लिए सबसे अच्छा अनुभव नहीं है.
ब्राउज़र की नई सुविधाओं का इस्तेमाल करना
हाल ही में, ज़्यादा डीपीआई वाली इमेज से जुड़ी समस्या के लिए, वेब प्लैटफ़ॉर्म के साथ काम करने के बारे में काफ़ी चर्चा हुई है. Apple ने हाल ही में इस स्पेस में अपनी जगह बनाई है. इसके लिए, उसने WebKit में image-set() सीएसएस फ़ंक्शन को शामिल किया है. इसलिए, यह सुविधा Safari और Chrome, दोनों पर काम करती है. यह एक सीएसएस फ़ंक्शन है, इसलिए image-set()
<img>
टैग की समस्या को हल नहीं करता. @srcset डालें. इससे यह समस्या हल हो जाती है. हालांकि, इस लेख को लिखने के समय तक, इसका कोई रेफ़रंस लागू नहीं किया गया है! अगले सेक्शन में, image-set
और srcset
के बारे में ज़्यादा जानकारी दी गई है.
ज़्यादा डीपीआई के लिए ब्राउज़र की सुविधाएं
आखिरकार, आपको कौनसा तरीका अपनाना है, यह आपकी ज़रूरतों पर निर्भर करता है. हालांकि, ध्यान रखें कि ऊपर बताए गए सभी तरीकों में कुछ कमियां हैं. हालांकि, आने वाले समय में जब image-set
और srcset का इस्तेमाल बड़े पैमाने पर किया जाएगा, तब वे इस समस्या के लिए सही समाधान होंगे. फ़िलहाल, सबसे सही तरीकों के बारे में बात करते हैं. इनकी मदद से, हम आने वाले समय में इस मकसद को पूरा कर पाएंगे.
सबसे पहले, इन दोनों में क्या अंतर है? image-set()
एक सीएसएस फ़ंक्शन है, जिसका इस्तेमाल बैकग्राउंड सीएसएस प्रॉपर्टी की वैल्यू के तौर पर किया जा सकता है. srcset, <img>
एलिमेंट के लिए खास तौर पर बनाया गया एट्रिब्यूट है. इसका सिंटैक्स भी image-set()
जैसा ही है.
इन दोनों टैग की मदद से, इमेज के एलान किए जा सकते हैं. हालांकि, srcset एट्रिब्यूट की मदद से यह भी कॉन्फ़िगर किया जा सकता है कि व्यूपोर्ट के साइज़ के आधार पर कौनसी इमेज लोड की जाए.
इमेज-सेट बनाने के सबसे सही तरीके
image-set()
सीएसएस फ़ंक्शन, -webkit-image-set()
के तौर पर उपलब्ध है. सिंटैक्स काफ़ी आसान है. इसमें एक या एक से ज़्यादा इमेज डिक्लेरेशन होते हैं, जिन्हें कॉमा लगाकर अलग किया जाता है. इनमें यूआरएल स्ट्रिंग या url()
फ़ंक्शन होता है. इसके बाद, उससे जुड़ा रिज़ॉल्यूशन होता है. उदाहरण के लिए:
background-image: -webkit-image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x
);
इससे ब्राउज़र को पता चलता है कि चुनने के लिए दो इमेज उपलब्ध हैं. इनमें से एक, 1x डिसप्ले के लिए ऑप्टिमाइज़ किया गया है और दूसरा, 2x डिसप्ले के लिए. इसके बाद, ब्राउज़र यह चुनता है कि किस वर्शन को लोड करना है. यह कई बातों पर निर्भर करता है. अगर ब्राउज़र ज़रूरत के मुताबिक स्मार्ट है, तो इसमें नेटवर्क की स्पीड भी शामिल हो सकती है. हालांकि, मुझे पता है कि फ़िलहाल इसे लागू नहीं किया गया है.
सही इमेज लोड करने के अलावा, ब्राउज़र उसे सही तरीके से स्केल भी करेगा. दूसरे शब्दों में, ब्राउज़र यह मानता है कि दो इमेज, एक इमेज के मुकाबले दोगुनी बड़ी हैं. इसलिए, वह दोगुनी इमेज को दो गुना कम कर देगा, ताकि इमेज पेज पर एक ही साइज़ में दिखे.
1x, 1.5x या Nx के बजाय, डिवाइस के पिक्सल डेंसिटी को डीपीआई में भी तय किया जा सकता है.
यह तरीका, उन ब्राउज़र पर काम नहीं करता जो image-set
प्रॉपर्टी के साथ काम नहीं करते. इनमें कोई इमेज नहीं दिखेगी! यह साफ़ तौर पर खराब है. इसलिए, इस समस्या को हल करने के लिए, आपको फ़ॉलबैक (या फ़ॉलबैक की सीरीज़) का इस्तेमाल करना होगा:
background-image: url(icon1x.jpg);
background-image: -webkit-image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x
);
/* This will be useful if image-set gets into the platform, unprefixed.
Also include other prefixed versions of this */
background-image: image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x
);
ऊपर दिया गया कोड, उन ब्राउज़र में सही ऐसेट लोड करेगा जो इमेज-सेट की सुविधा के साथ काम करते हैं. अगर ऐसा नहीं होता है, तो यह 1x ऐसेट पर स्विच कर देगा. ध्यान रखें कि image-set()
ब्राउज़र के साथ काम करने वाले ऐप्लिकेशन कम हैं. इसलिए, ज़्यादातर उपयोगकर्ता एजेंट को 1x एसेट मिलेगी.
यह डेमो सही इमेज लोड करने के लिए image-set()
का इस्तेमाल करता है. अगर यह CSS फ़ंक्शन काम नहीं करता है, तो यह 1x एसेट पर स्विच कर देता है.
अब आपके मन में यह सवाल आ सकता है कि image-set()
के लिए सिर्फ़ पॉलीफ़िल (यानी, इसके लिए JavaScript शिम बनाएं) क्यों न किया जाए और इसे खत्म कर दिया जाए? जैसा कि पता चला है, सीएसएस फ़ंक्शन के लिए बेहतर पॉलीफ़िल लागू करना काफ़ी मुश्किल है. (इसकी पूरी जानकारी के लिए, www-style वाली इस बातचीत को देखें).
इमेज का srcset
यहां srcset का एक उदाहरण दिया गया है:
<img alt="my awesome image"
src="banner.jpeg"
srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">
जैसा कि आप देख सकते हैं, image-set
के ज़रिए दिए गए x एलान के अलावा,
srcset एलिमेंट में w और h वैल्यू भी होती हैं. ये वैल्यू, व्यूपोर्ट के साइज़ से मेल खाती हैं. इससे, सबसे सही वर्शन दिखाने की कोशिश की जाती है. ऊपर दी गई इमेज, 640 पिक्सल से कम व्यूपोर्ट चौड़ाई वाले डिवाइसों पर banner-phone.jpeg, छोटी स्क्रीन वाले हाई डीपीआई डिवाइसों पर banner-phone-HD.jpeg, 640 पिक्सल से ज़्यादा स्क्रीन वाले हाई डीपीआई डिवाइसों पर banner-HD.jpeg, और बाकी सभी डिवाइसों पर banner.jpeg दिखाएगी.
इमेज एलिमेंट के लिए image-set का इस्तेमाल करना
ज़्यादातर ब्राउज़र में, img एलिमेंट पर srcset एट्रिब्यूट लागू नहीं होता. इसलिए, हो सकता है कि आप अपने img एलिमेंट को <div>
s के साथ बैकग्राउंड में बदलना चाहें और इमेज-सेट वाले तरीके का इस्तेमाल करें. हालांकि, इसमें कुछ शर्तें लागू होंगी. यहां समस्या यह है कि <img>
टैग की सेमैंटिक वैल्यू लंबे समय तक बनी रहती है. आम तौर पर, यह वेब क्रॉलर और सुलभता के लिहाज़ से ज़्यादा ज़रूरी है.
अगर -webkit-image-set
का इस्तेमाल किया जाता है, तो हो सकता है कि आप बैकग्राउंड सीएसएस प्रॉपर्टी का इस्तेमाल करना चाहें. इस तरीके का इस्तेमाल करने पर, आपको इमेज का साइज़ बताना होगा. अगर 1x इमेज का इस्तेमाल नहीं किया जा रहा है, तो साइज़ का पता नहीं चलता.
ऐसा करने के बजाय, कॉन्टेंट की सीएसएस प्रॉपर्टी का इस्तेमाल इस तरह किया जा सकता है:
<div id="my-content-image"
style="content: -webkit-image-set(
url(icon1x.jpg) 1x,
url(icon2x.jpg) 2x);">
</div>
इससे, devicePixelRatio के आधार पर इमेज अपने-आप स्केल हो जाएगी. ऊपर बताई गई तकनीक को इस्तेमाल करने का यह उदाहरण देखें. इसमें image-set
के साथ काम न करने वाले ब्राउज़र के लिए, url()
का फ़ॉलबैक भी दिया गया है.
srcset को पॉलीफ़िल करना
srcset
की एक सुविधा यह है कि यह अपने-आप फ़ॉलबैक पर स्विच हो जाता है.
अगर srcset एट्रिब्यूट लागू नहीं किया गया है, तो सभी ब्राउज़र को src एट्रिब्यूट को प्रोसेस करने का तरीका पता होता है. साथ ही, यह सिर्फ़ एक एचटीएमएल एट्रिब्यूट है. इसलिए, JavaScript की मदद से polyfills बनाए जा सकते हैं.
इस पॉलीफ़िल में यूनिट टेस्ट होते हैं, ताकि यह पक्का किया जा सके कि यह स्पेसिफ़िकेशन के ज़्यादा से ज़्यादा करीब हो. इसके अलावा, कुछ जांच की सुविधाएं भी मौजूद हैं. इनकी मदद से, srcset को नेटिव तौर पर लागू करने पर, पॉलीफ़िल को किसी भी कोड को लागू करने से रोका जा सकता है.
यहां पॉलीफ़िल के डेमो की जानकारी दी गई है.
नतीजा
हाई डीपीआई वाली इमेज की समस्या को हल करने का कोई आसान तरीका नहीं है.
सबसे आसान तरीका यह है कि इमेज का इस्तेमाल न करें और इसके बजाय, SVG और सीएसएस का इस्तेमाल करें. हालांकि, यह हमेशा सही नहीं होता. खास तौर पर, अगर आपकी साइट पर अच्छी क्वालिटी की इमेज मौजूद हैं.
JS, CSS, और सर्वर-साइड के इस्तेमाल के तरीकों के अपने फ़ायदे और कमियां हैं. हालांकि, सबसे बेहतर तरीका यह है कि ब्राउज़र की नई सुविधाओं का फ़ायदा लिया जाए. हालांकि, image-set
और srcset
के लिए ब्राउज़र की सहायता अब भी पूरी नहीं हुई है, लेकिन फ़िलहाल इनका इस्तेमाल करने के लिए फ़ॉलबैक उपलब्ध हैं.
खास जानकारी के तौर पर, मेरे सुझाव यहां दिए गए हैं:
- बैकग्राउंड इमेज के लिए, image-set का इस्तेमाल करें. साथ ही, उन ब्राउज़र के लिए सही फ़ॉलबैक का इस्तेमाल करें जिन पर यह काम नहीं करता.
- कॉन्टेंट इमेज के लिए, srcset polyfill का इस्तेमाल करें या image-set का इस्तेमाल करके फ़ॉलबैक करें (ऊपर देखें).
- अगर आपको इमेज क्वालिटी में समझौता करना है, तो ज़्यादा कंप्रेस की गई दो इमेज का इस्तेमाल करें.