abox.tools

भाषा: हिन्दी

तस्वीर को अपनी CSS के भीतर कब रखें, और कब नहीं

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

तस्वीर से data URI खोलें पूरी तस्वीर, टेक्स्ट की एक पंक्ति में। सीधे CSS या HTML में चिपका दीजिए।

Markdown के रूप में देखें

छोटा जवाब

तस्वीर से data URI खोलिए, तस्वीर भीतर छोड़ दीजिए, CSS कस्टम प्रॉपर्टी चुनिए, और वह पंक्ति अपनी स्टाइलशीट के सिरे पर चिपका दीजिए। फिर जहाँ भी ज़रूरत हो, उसे background-image: var(--logo) की तरह इस्तेमाल कीजिए।

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

data URI असल में है क्या

ऐसा पता जो किसी चीज़ की तरफ़ इशारा करने के बजाय खुद वही चीज़ समेटे रहता है। जहाँ स्टाइलशीट आम तौर पर लिखती

background-image: url("logo.png");

और ब्राउज़र जाकर logo.png ले आता, वहाँ data URI लिखता है

background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...");

और लाने को कुछ बचता ही नहीं: तस्वीर पहले से वहीं है, अक्षरों में लिखी हुई। इसके तीन हिस्से हैं। data: स्कीम है। image/png मीडिया टाइप है, और ब्राउज़र उस पर पूरा भरोसा कर लेता है, और इस पर बात आगे होगी। कॉमा के बाद जो कुछ है वह फ़ाइल है।

पूरा विचार बस यही है। यह कोई तिकड़म या जुगाड़ नहीं है; यह 1998 से मानकों में है और उसके बाद निकले हर ब्राउज़र में चलता है।

इससे आपको क्या मिलता है: एक कम चक्कर

बचत बैंडविड्थ की नहीं है। बचत रिक्वेस्ट की है।

ब्राउज़र logo.png तब तक माँग ही नहीं सकता जब तक वह उस स्टाइलशीट को न पढ़ ले जो उसका ज़िक्र करती है, और स्टाइलशीट तब तक नहीं पढ़ सकता जब तक उसे ले न आए। इसलिए आम बैकग्राउंड तस्वीर पेज लोड में कम से कम दो चक्करों की गहराई पर होती है, और धीमे नेटवर्क पर फ़ोन में एक चक्कर दो-एक सौ मिलीसेकंड का हो सकता है, फ़ाइल चाहे कितनी भी छोटी हो। 600 बाइट के तीर के निशान को भेजने में लगभग कुछ नहीं लगता और फिर भी उसे पहुँचने में सेकंड का चौथाई हिस्सा लग सकता है।

भीतर रखा हो तो वह स्टाइलशीट के साथ ही पहुँच जाता है। पूरा फ़ायदा बस यही है, और पहली स्क्रीन पर दिखने वाले छोटे आइकन के लिए यह असली फ़ायदा है।

इसकी कीमत: एक-तिहाई, और उसके बाद कैशिंग

base64 करीब एक-तिहाई जोड़ देता है। फ़ाइल के तीन बाइट चार अक्षर बन जाते हैं, क्योंकि सिर्फ़ URL में चलने वाले अक्षरों से मनमाने बाइट लिखने में इतना ही लगता है। ऐसा कोई चतुर एनकोडर है ही नहीं जो इससे बच जाए। 9 KB की PNG स्टाइलशीट में 12 KB है।

कंप्रेशन उसे वापस नहीं करता। यही वह हिस्सा है जिसे लोग मानकर चल पड़ते हैं। Gzip और Brotli दोहराव ढूँढ़कर काम करते हैं, और PNG, JPEG तथा WebP पहले से कंप्रेस हो चुके होते हैं, इसलिए उनमें दोहराव बहुत कम बचा होता है, और base64 उसमें कुछ जोड़ता भी नहीं। व्यवहार में उस एक-तिहाई का दसवाँ हिस्सा भर वापस मिलता है, पूरा नहीं। (SVG उलटा मामला है, और अगला हिस्सा उसी के बारे में है।)

वह फ़ाइल रह ही नहीं जाती। यही वह कीमत है जो आपकी की गई किसी भी माप में दिखेगी नहीं, और साइज़ बढ़ने पर मायने यही रखती है:

मोटी हदें, जो वहाँ हैं जहाँ सलाह बदलती है, न कि वहाँ जहाँ ब्राउज़र कुछ अलग करता है: करीब 2 KB से नीचे यह साफ़ फ़ायदे का सौदा है; करीब 10 KB तक हर पेज पर दिखने वाली चीज़ के लिए यह आम तौर पर पैसा वसूल रहता है; 50 KB के आगे यह ऐसी गलती है जिसका कोई त्रुटि संदेश नहीं आता। टूल बता देता है कि हर नतीजा किस पट्टी में गिरता है, और बगल में अक्षरों की गिनती भी लिख देता है।

निर्गम वाला कार्ड: base64 डेटा URI वाला एक CSS नियम, और बगल में मूल फ़ाइल का नाप तथा एनकोड किया हुआ नाप।
एनकोड की गई नकल उस फ़ाइल से लगभग एक तिहाई बड़ी होती है जिससे वह बनी। यही वह कीमत है जिसकी बात यह हिस्सा करता है, और वह खोजे जाने के लिए छोड़ी नहीं गई, लिखी हुई है।

SVG को base64 कभी मत कीजिए

भीतर रखी तस्वीरों में यह अकेली सबसे आम गलती है, और यह लोगों से जितनी होती है उतनी ही एक्सपोर्टर और बिल्ड प्लगिन से भी।

SVG टेक्स्ट है। URL टेक्स्ट पहले से ढो सकता है। गिनती के कुछ ही अक्षरों को बचाना पड़ता है, यानी %, #, <, > और वह उद्धरण चिह्न जिसमें आपने उसे लपेटा। बाकी सब कुछ ठीक वैसा ही छोड़ा जा सकता है। उसे इस तरह एनकोड करने पर ऐसा URI मिलता है जो उसी फ़ाइल के base64 से आम तौर पर करीब पाँचवाँ हिस्सा छोटा होता है, और जो उसके बाद शोर की तरह नहीं, टेक्स्ट की तरह कंप्रेस होता है।

वह पढ़ने लायक भी रहता है:

background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E...");

आप viewBox देख सकते हैं। आप अपने एडिटर में बिना कुछ डिकोड किए भरने का रंग बदल सकते हैं। उसी फ़ाइल को base64 कीजिए और वह अक्षरों की ऐसी दीवार बन जाती है जिसे कोई दोबारा कभी नहीं छुएगा। तस्वीर से data URI जो कुछ भी SVG निकलता है उसके लिए यह अपने आप करता है, और जो इक्का-दुक्का टूलचेन ;base64 पर ही अड़े, उसके लिए एक चेकबॉक्स भी रखता है।

वह कोटेशन की गलती जो सिर्फ़ SVG को तोड़ती है

CSS आपको url() बिना उद्धरण चिह्नों के लिखने देती है, और आम फ़ाइल-नाम के लिए यह ठीक भी है:

background-image: url(logo.png);

percent-encode की गई SVG के साथ वही कीजिए और वह टूट जाती है। बिना उद्धरण वाला url() टोकन पहले स्पेस, कोष्ठक, उद्धरण चिह्न या कंट्रोल कैरेक्टर पर खत्म हो जाता है, और SVG स्पेसों से भरी होती है, हर एट्रिब्यूट के बीच और किसी पाथ की हर संख्या के बीच। तब वह घोषणा अमान्य हो जाती है, CSS अमान्य घोषणाएँ चुपचाप फेंक देती है, और आपको न बैकग्राउंड मिलता है न कोई त्रुटि।

इसका इलाज है उद्धरण चिह्न, हर बार:

background-image: url("data:image/svg+xml,%3Csvg ... %3E");

इसीलिए एनकोडर को स्पेस बचाने की ज़रूरत भी नहीं पड़ती, क्योंकि उद्धरण वाले URL के भीतर वे बिलकुल वैध हैं, और हर एक को %20 लिखने में फ़ाइल के हर स्पेस पर तीन अक्षर लगते। ये दोनों फ़ैसले साथ चलते हैं: URI को उद्धरण में रखिए, और आप स्पेसों को छू ही नहीं सकते। टूल जो भी रूप बनाता है, वह ठीक इसी वजह से उद्धरण चिह्नों में रहता है।

मीडिया टाइप का सही होना ज़रूरी है

data URI अपना टाइप खुद घोषित करता है, और ब्राउज़र उसकी बात मान लेता है। यहाँ वैसी कोई सूँघकर पहचानने वाली वापसी नहीं है जैसी लाई गई फ़ाइल के लिए होती है: किसी ऐसी चीज़ के बारे में image/png कह दीजिए जो असल में JPEG है, और तस्वीर बनती ही नहीं। कहीं भी कोई काम का संदेश भी नहीं मिलता।

यह इसलिए मायने रखता है कि फ़ाइल एक्सटेंशन झूठ बोलते हैं। JPEG के रूप में एक्सपोर्ट होकर logo.png नाम पा चुकी फ़ोटो किसी डिस्क पर मिलना आम बात है। दूसरी तरफ़, इमेज फ़ाइल के पहले कुछ बाइट बिना किसी संदेह के बता देते हैं कि वह है क्या, क्योंकि हर फ़ॉर्मैट का अपना हस्ताक्षर होता है। इसलिए टूल को नाम नहीं, फ़ाइल पढ़नी चाहिए। यहाँ वाला यही करता है, और जब दोनों न मिलें तो आपको बता देता है।

दो फ़ॉर्मैट जानने लायक हैं क्योंकि वे उलझन भरे ढंग से नाकाम होते हैं। HEIC, जिसमें iPhone फ़ोटो खींचता है, और TIFF, जो स्कैनर बनाते हैं, दोनों बिलकुल वैध data URI बनाते हैं जिन्हें Safari के सिवा कोई ब्राउज़र खींचेगा नहीं। URI टूटा हुआ नहीं है; वह फ़ॉर्मैट ही ऐसा नहीं है जिसे वेब समर्थन देता हो। पहले बदल लीजिए।

वह मेटाडेटा जिसे प्रकाशित करने का आपका इरादा नहीं था

data URI फ़ाइल की बाइट-दर-बाइट नकल है। कुछ भी डिकोड करके दोबारा एनकोड नहीं होता, और आम तौर पर मकसद भी यही होता है, क्योंकि इससे कोई क्वालिटी नहीं खोती। पर इसका मतलब यह भी है कि फ़ाइल में मौजूद बाकी सब कुछ साथ चला आता है।

फ़ोन से सीधे निकली फ़ोटोग्राफ़ EXIF ढोती है: वे GPS निर्देशांक जहाँ वह खींची गई, समय, कैमरे का मॉडल और अक्सर उसका सीरियल नंबर। यह फ़ाइल का 30 KB तक हो सकता है। भीतर रखने पर वह आपकी स्टाइलशीट में 40 KB base64 बन जाता है, हर पेज के क्रिटिकल पाथ पर। और साथ में रिपॉज़िटरी में कमिट हो चुका एक घर का पता, ऐसे रूप में जिसे देखने की बात किसी के दिमाग में कभी नहीं आएगी।

उसे पहले EXIF व्यूअर और रिमूवर से हटा दीजिए, जो तस्वीर को छुए बिना कंटेनर दोबारा लिख देता है; उसके लिए भी एक गाइड है। तस्वीर से data URI वाला टूल पढ़ लेता है कि JPEG, PNG या WebP में कितना मेटाडेटा है और कुछ भी कॉपी करने से पहले बता देता है।

मिल जाने के बाद उसे रखें कहाँ

अगर तस्वीर एक ही नियम में आती है, तो URI उसी नियम में रख दीजिए। अगर वह एक से ज़्यादा में आती है, और आइकन आम तौर पर आते ही हैं जब आप hover वाली स्थिति और डार्क थीम भी गिन लें, तो उसे एक ही बार कस्टम प्रॉपर्टी के रूप में घोषित कीजिए:

:root {
  --icon-search: url("data:image/svg+xml,%3Csvg ... %3E");
}

.search-field { background-image: var(--icon-search); }
.search-button::before { content: var(--icon-search); }

चार नियमों में चिपकाया गया 3 KB का URI स्टाइलशीट में 12 KB है और आइकन बदलने पर संपादित करने को चार जगहें। कस्टम प्रॉपर्टी में दोनों एक-एक हैं। थीमिंग को चलने लायक बनाने वाला ढाँचा भी यही है: किसी मीडिया क्वेरी के भीतर --icon-search दोबारा घोषित कीजिए और उसका हर इस्तेमाल उसी के पीछे चला आता है।

CSS के बजाय <img> टैग के लिए, width और height ज़रूर लिखिए। भीतर रखी तस्वीर तुरंत लोड हो जाती है, इसलिए साइज़ का न होना ऐसा लेआउट खिसकाव है जो दिखने के लिए भी बहुत तेज़ी से होता है और फिर भी आपके खिलाफ़ गिना जाता है। अपवाद SVG है: जो सिर्फ़ viewBox ढोती है उसका अपना कोई पिक्सल साइज़ होता ही नहीं, और टैग पर ब्राउज़र का डिफ़ॉल्ट ⁦300×150⁩ लिख देना उस तस्वीर को ऐसे साइज़ पर टाँक देता है जो किसी ने चुना ही नहीं।

alt तब तक खाली रहने दीजिए जब तक उसमें रखने को आपके पास कुछ सच्चा न हो। सिर्फ़ आप जानते हैं कि तस्वीर कोई अर्थ ढो रही है या बस सजावट है, और फ़ाइल के नाम से अंदाज़ा लगाकर लिखा गया विवरण स्क्रीन रीडर इस्तेमाल करने वाले के लिए किसी विवरण के न होने से भी बुरा है।

आकार वाला कार्ड: बटन जो चुनते हैं कि क्या निकले, CSS का पृष्ठभूमि नियम, img टैग या सिर्फ़ URI, और base64 या सीधा SVG चुनने का स्विच।
कहाँ जाना है यही तय करता है कि क्या निकलेगा, इसलिए यह पहले पूछा जाता है, कॉपी-पेस्ट के अभ्यास पर नहीं छोड़ा जाता।

जब जवाब हो “मत कीजिए”

तस्वीर एनकोड होकर करीब 50 KB से ऊपर जाती है, तो उसे भीतर रखना ही गलत रास्ता है, और एनकोडिंग में कितनी भी सावधानी बरतने से यह ठीक नहीं होता। आज़माने लायक क्रम में विकल्प ये हैं।

इसमें से किसी के लिए अपलोड की ज़रूरत नहीं

किसी फ़ाइल को base64 में एनकोड करना गणित है। यह ब्राउज़र के पास शुरू से मौजूद दो फ़ंक्शन भर हैं, btoa और encodeURIComponent। किसी तस्वीर के बस अलग ढंग से लिखे जाने के लिए सर्वर तक जाकर लौटने की कोई तकनीकी वजह है ही नहीं। जो कन्वर्टर यह करने के लिए आपकी फ़ाइल अपलोड करता है, वह उसे अपनी वजहों से अपलोड कर रहा है, आपकी वजहों से नहीं।

यहाँ का टूल उसे कहीं भेजता नहीं: पेज की Content-Security-Policy उन सारे पतों के नाम गिना देती है जिनसे वह संपर्क कर सकता है, और उनमें से एक भी इस साइट का नहीं है। अगर बताया जाना काफ़ी न लगे तो पेज लोड कीजिए, इंटरनेट काट दीजिए, और तब भी कुछ एनकोड करके देख लीजिए। क्या ऑनलाइन कन्वर्टर पर फ़ाइलें अपलोड करना सुरक्षित है? ऐसी ही तीन और जाँचें बताता है, जो आप किसी भी टूल पर चला सकते हैं।