हाल ही में, क्रिस कॉयर ने एक ब्लॉग पोस्ट लिखा. इसमें यह सवाल पूछा गया:
अब जब कंटेनर क्वेरी सभी ब्राउज़र इंजन में काम करती हैं, तो ज़्यादा डेवलपर उनका इस्तेमाल क्यों नहीं कर रहे?
क्रिस की पोस्ट में कई संभावित वजहों के बारे में बताया गया है. उदाहरण के लिए, जागरूकता की कमी, पुरानी आदतें मुश्किल से खत्म हो सकती हैं. हालांकि, इसकी एक खास वजह सबसे अलग है.
कुछ डेवलपर का कहना है कि वे अब कंटेनर क्वेरी का इस्तेमाल करना चाहते हैं, लेकिन उन्हें लगता है कि वे ऐसा नहीं कर पाएंगे क्योंकि अब भी उन्हें पुराने ब्राउज़र के साथ काम करना है.
जैसा कि आपने शीर्षक से अनुमान लगा लिया होगा, हमें लगता है कि ज़्यादातर डेवलपर अब प्रोडक्शन में कंटेनर क्वेरी का इस्तेमाल कर सकते हैं. भले ही, आपको पुराने ब्राउज़र का इस्तेमाल करना क्यों न हो. इस पोस्ट में, आपको ऐसा करने का सुझाव दिया गया है.
व्यावहारिक अप्रोच
अगर आपको अभी अपने कोड में कंटेनर क्वेरी का इस्तेमाल करना है, लेकिन आपको सभी ब्राउज़र में अनुभव एक जैसा दिखाना है, तो उन ब्राउज़र के लिए JavaScript पर आधारित फ़ॉलबैक लागू करें जो कंटेनर क्वेरी के साथ काम नहीं करते हैं.
अब सवाल यह उठता है कि: फ़ॉलबैक कितना पूरा होना चाहिए?
किसी भी दूसरे कार्यक्रम की तरह, इस प्लैटफ़ॉर्म पर भी वीडियो की उपयोगिता और परफ़ॉर्मेंस के बीच अच्छा संतुलन बनाना ही चुनौती है. सीएसएस की सुविधाओं के लिए, अक्सर पूरे एपीआई को इस्तेमाल करना नामुमकिन होता है (पॉलीफ़िल का इस्तेमाल क्यों नहीं करें) देखें. हालांकि, फ़ंक्शन के उस मुख्य सेट की पहचान करके काफ़ी आगे जाया जा सकता है जिसका इस्तेमाल ज़्यादातर डेवलपर करना चाहते हैं. इसके बाद, उन सुविधाओं के लिए फ़ॉलबैक को ऑप्टिमाइज़ किया जा सकता है.
हालांकि, "फ़ंक्शन का मुख्य सेट" क्या है क्या है, जो ज़्यादातर डेवलपर कंटेनर क्वेरी के लिए चाहते हैं? इस सवाल का जवाब देने के लिए, यह देखें कि फ़िलहाल ज़्यादातर डेवलपर मीडिया क्वेरी के साथ रिस्पॉन्सिव साइटें कैसे बनाते हैं.
ज़्यादातर आधुनिक डिज़ाइन सिस्टम और कॉम्पोनेंट लाइब्रेरी में, मोबाइल को प्राथमिकता देने वाले सिद्धांतों के हिसाब से स्टैंडर्ड बनाया गया है. इन्हें पहले से तय ब्रेकपॉइंट (जैसे कि SM
, MD
, LG
, XL
) के सेट का इस्तेमाल करके लागू किया गया है. कॉम्पोनेंट, डिफ़ॉल्ट रूप से छोटी स्क्रीन पर अच्छी तरह से दिखने के लिए ऑप्टिमाइज़ किए जाते हैं. इसके बाद, बड़ी स्क्रीन की चौड़ाई के तय सेट के साथ काम करने के लिए, स्टाइल को शर्त के साथ लागू किया जाता है. (इसके उदाहरण देखने के लिए, बूटस्ट्रैप और Tailwind दस्तावेज़ देखें.)
यह तरीका कंटेनर-आधारित डिज़ाइन सिस्टम के लिए भी उतना ही कारगर है, जितना कि व्यूपोर्ट-आधारित डिज़ाइन सिस्टम के लिए है. ज़्यादातर मामलों में, डिज़ाइनर के लिए यह ज़रूरी नहीं कि स्क्रीन या व्यूपोर्ट कितना बड़ा है. यह बात यह है कि कॉम्पोनेंट के लिए कितनी जगह उपलब्ध है. दूसरे शब्दों में, ब्रेकपॉइंट पूरे व्यूपोर्ट (और पूरे पेज पर लागू) के मुताबिक होने के बजाय, ब्रेकपॉइंट, साइडबार, मॉडल डायलॉग या पोस्ट बॉडी जैसे खास कॉन्टेंट एरिया पर लागू होंगे.
अगर आपको मोबाइल-फ़र्स्ट, ब्रेकपॉइंट पर आधारित तरीके (जो ज़्यादातर डेवलपर फ़िलहाल इस्तेमाल करते हैं) की सीमाओं के अंदर काम करने में परेशानी हो रही है, तो उस तरीके के लिए कंटेनर-आधारित फ़ॉलबैक लागू करना, हर एक कंटेनर क्वेरी सुविधा के लिए पूरा सहायता लागू करने की तुलना में बहुत आसान है.
अगले सेक्शन में यह बताया गया है कि ये सब कैसे काम करते हैं. साथ ही, सिलसिलेवार निर्देशों की मदद से यह भी बताया गया है कि किसी मौजूदा साइट पर इन्हें कैसे लागू किया जा सकता है.
यह कैसे काम करता है
पहला चरण: @media
नियमों के बजाय @container
नियमों का इस्तेमाल करने के लिए, कॉम्पोनेंट स्टाइल अपडेट करना
इस पहले चरण में, अपनी साइट पर मौजूद ऐसे किसी भी कॉम्पोनेंट की पहचान करें जिसके बारे में आपको लगता है कि व्यूपोर्ट के मुताबिक साइज़ के बजाय कंटेनर के आधार पर साइज़ बदलने से फ़ायदा होगा.
यह जानने के लिए कि यह रणनीति कैसे काम करती है, बस एक या दो कॉम्पोनेंट के साथ शुरुआत करना अच्छा रहता है. हालांकि, अगर आपको अपने 100% कॉम्पोनेंट को कंटेनर-आधारित स्टाइल में बदलना है, तो भी कोई दिक्कत नहीं है! इस रणनीति की सबसे अच्छी बात यह है कि ज़रूरत पड़ने पर इसे बढ़ाया भी जा सकता है.
जिन कॉम्पोनेंट को अपडेट करना है उनकी पहचान करने के बाद, आपको उन कॉम्पोनेंट में मौजूद हर @media
के नियम को बदलना होगा सीएसएस को @container
नियम में बदलें.
यहां दिए गए उदाहरण में बताया गया है कि यह .photo-gallery
कॉम्पोनेंट पर कैसा दिख सकता है. यह डिफ़ॉल्ट रूप से एक कॉलम होता है. इसके बाद, इसके लेआउट को अपडेट करने के लिए @media
नियमों का इस्तेमाल करता है, ताकि एमडी और एक्सएल ब्रेकपॉइंट में दो और तीन कॉलम बन सकें (इसके लिए):
.photo-gallery {
display: grid;
grid-template-columns: 1fr;
}
/* Styles for the `MD` breakpoint */
@media (min-width: 800px) {
.photo-gallery {
grid-template-columns: 1fr 1fr;
}
}
/* Styles for the `XL` breakpoint */
@media (min-width: 1200px) {
.photo-gallery {
grid-template-columns: 1fr 1fr 1fr;
}
}
.photo-gallery
कॉम्पोनेंट को अपडेट करके, @container
के नियमों का इस्तेमाल करने के लिए, सबसे पहले सीएसएस में @media
स्ट्रिंग को @container
स्ट्रिंग से बदलें. इन दो नियमों का व्याकरण काफ़ी समान है. कई मामलों में, आपको बस इतना ही बदलने की ज़रूरत है.
आपकी साइट के डिज़ाइन के आधार पर, आपको साइज़ की शर्तों को भी अपडेट करना पड़ सकता है. खास तौर पर तब, जब आपकी साइट के @media
नियमों से यह अनुमान लगाया जा रहा हो कि अलग-अलग व्यूपोर्ट के साइज़ में, अलग-अलग कॉम्पोनेंट के लिए कितनी जगह उपलब्ध होगी.
उदाहरण के लिए, अगर पिछले उदाहरण में MD
और XL
ब्रेकपॉइंट पर .photo-gallery
सीएसएस के लिए स्टाइल को यह माना गया है कि उन ब्रेकपॉइंट पर 200 पिक्सल चौड़ा साइडबार दिखाया जाएगा, तो @container
नियमों के लिए साइज़ की शर्तें करीब 200 पिक्सल कम होनी चाहिए. यह मानते हुए कि "कंटेनर" .photo-gallery
कॉम्पोनेंट के लिए एलिमेंट में साइडबार शामिल नहीं होगा.
.photo-gallery
सीएसएस को @media
नियमों से @container
नियमों में बदलने के लिए, सभी बदलावों के बारे में यहां बताया गया है:
/* Before, using the original breakpoint sizes: */
@media (min-width: 800px) { /* ... */ }
@media (min-width: 1200px) { /* ... */ }
/* After, with the breakpoint sizes reduced by 200px: */
@container (min-width: 600px) { /* ... */ }
@container (min-width: 1000px) { /* ... */ }
ध्यान दें कि आपको डिक्लेरेशन ब्लॉक में किसी भी स्टाइल को बदलने की ज़रूरत नहीं है, क्योंकि वे यह दिखाते हैं कि कॉम्पोनेंट कैसे दिखता है, न कि कब खास स्टाइल को लागू करना चाहिए.
अपने कॉम्पोनेंट के स्टाइल को @media
नियमों से @container
नियमों में अपडेट करने के बाद, अगला चरण अपने कंटेनर एलिमेंट को कॉन्फ़िगर करना है.
दूसरा चरण: अपने एचटीएमएल में कंटेनर एलिमेंट जोड़ना
पिछले चरण में तय किए गए कॉम्पोनेंट के स्टाइल, जो कंटेनर एलिमेंट के साइज़ पर आधारित होते हैं. अगले चरण में यह तय किया जाता है कि आपके पेज पर कौनसे एलिमेंट ऐसे कंटेनर एलिमेंट होने चाहिए जिनके साइज़ के हिसाब से @container
नियम तय होंगे.
सीएसएस में किसी भी एलिमेंट को कंटेनर एलिमेंट माना जा सकता है. इसके लिए, container-type
प्रॉपर्टी को size
या inline-size
पर सेट करें. अगर आपके कंटेनर के नियम चौड़ाई पर आधारित हैं, तो आम तौर पर inline-size
का इस्तेमाल करना है.
इस बेसिक एचटीएमएल स्ट्रक्चर वाली साइट का इस्तेमाल करें:
<body>
<div class="sidebar">...</div>
<div class="content">...</div>
</body>
इस साइट पर .sidebar
और .content
एलिमेंट का कंटेनर बनाने के लिए, अपनी सीएसएस में यह नियम जोड़ें:
.content, .sidebar {
container-type: inline-size;
}
कंटेनर क्वेरी के साथ काम करने वाले ब्राउज़र के लिए, आपको पिछले चरण में तय की गई कॉम्पोनेंट स्टाइल को मुख्य कॉन्टेंट एरिया या साइडबार के हिसाब से बनाना होता है. यह इस बात पर निर्भर करता है कि वे किस एलिमेंट में मौजूद हैं.
हालांकि, कंटेनर क्वेरी का समर्थन न करने वाले ब्राउज़र के लिए, कुछ अतिरिक्त काम करना होता है.
आपको कोई ऐसा कोड जोड़ना होगा जो कंटेनर एलिमेंट के साइज़ में बदलाव का पता लगा सके और फिर उन बदलावों के आधार पर डीओएम को इस तरह अपडेट करे कि आपका सीएसएस हुक कर सके.
अच्छी बात यह है कि इस काम के लिए ज़रूरी कोड बहुत कम है. इसे एक ऐसे कॉम्पोनेंट के तौर पर दिखाया जा सकता है जिसे शेयर किया गया हो. इसका इस्तेमाल किसी भी साइट और कॉन्टेंट एरिया में किया जा सकता है.
यह कोड, फिर से इस्तेमाल किए जा सकने वाले <responsive-container>
एलिमेंट के बारे में बताता है. यह साइज़ में होने वाले बदलावों को अपने-आप सुनता है. साथ ही, उन ब्रेकपॉइंट क्लास को जोड़ता है जिन्हें आपकी सीएसएस, इन चीज़ों के आधार पर स्टाइल कर सकती है:
// A mapping of default breakpoint class names and min-width sizes.
// Redefine these (or add more) as needed based on your site's design.
const defaultBreakpoints = {SM: 400, MD: 600 LG: 800, XL: 1000};
// A resize observer that monitors size changes to all <responsive-container>
// elements and calls their `updateBreakpoints()` method with the updated size.
const ro = new ResizeObserver((entries) => {
entries.forEach((e) => e.target.updateBreakpoints(e.contentRect));
});
class ResponsiveContainer extends HTMLElement {
connectedCallback() {
const bps = this.getAttribute('breakpoints');
this.breakpoints = bps ? JSON.parse(bps) : defaultBreakpoints;
this.name = this.getAttribute('name') || '';
ro.observe(this);
}
disconnectedCallback() {
ro.unobserve(this);
}
updateBreakpoints(contentRect) {
for (const bp of Object.keys(this.breakpoints)) {
const minWidth = this.breakpoints[bp];
const className = this.name ? `${this.name}-${bp}` : bp;
this.classList.toggle(className, contentRect.width >= minWidth);
}
}
}
self.customElements.define('responsive-container', ResponsiveContainer);
यह कोड एक ResizeObserver बनाता है जो डीओएम में किसी भी <responsive-container>
एलिमेंट के साइज़ में बदलाव को अपने-आप सुनता है. अगर साइज़ में किया गया बदलाव, किसी तय ब्रेकपॉइंट साइज़ से मेल खाता है, तो उस ब्रेकपॉइंट नाम वाली क्लास को एलिमेंट में जोड़ दिया जाता है. साथ ही, अगर शर्त पूरी नहीं होती, तो उसे हटा दिया जाता है.
उदाहरण के लिए, अगर <responsive-container>
एलिमेंट का width
600 से 800 पिक्सल (कोड में सेट की गई डिफ़ॉल्ट ब्रेकपॉइंट वैल्यू के आधार पर) के बीच है, तो SM
और MD
क्लास जोड़ दी जाएंगी, जैसे कि:
<responsive-container class="SM MD">...</responsive-container>
इन क्लास की मदद से, उन ब्राउज़र के लिए फ़ॉलबैक स्टाइल तय किए जा सकते हैं जिन पर कंटेनर क्वेरी काम नहीं करती हैं (तीसरा चरण: अपने सीएसएस में फ़ॉलबैक स्टाइल जोड़ना देखें).
अगर आपको इस कंटेनर एलिमेंट का इस्तेमाल करने के लिए, पिछले एचटीएमएल कोड को अपडेट करना है, तो साइडबार और मुख्य कॉन्टेंट के <div>
एलिमेंट को <responsive-container>
एलिमेंट में बदलें:
<body>
<responsive-container class="sidebar">...</responsive-container>
<responsive-container class="content">...</responsive-container>
</body>
ज़्यादातर मामलों में, <responsive-container>
एलिमेंट को पसंद के मुताबिक बनाए बिना इस्तेमाल किया जा सकता है. हालांकि, अगर आपको इसे अपनी पसंद के मुताबिक बनाना है, तो ये विकल्प उपलब्ध हैं:
- कस्टम ब्रेकपॉइंट साइज़: यह कोड, डिफ़ॉल्ट ब्रेकपॉइंट क्लास के नामों और कम से कम चौड़ाई वाले साइज़ के सेट का इस्तेमाल करता है. हालांकि, आपको डिफ़ॉल्ट ब्रेकपॉइंट साइज़ को अपनी पसंद के मुताबिक बदलना होता है.
breakpoints
एट्रिब्यूट का इस्तेमाल करके, हर एलिमेंट के आधार पर इन वैल्यू को बदला भी जा सकता है. - नाम वाले कंटेनर: यह कोड
name
एट्रिब्यूट पास करके, नाम वाले कंटेनर के लिए भी काम करता है. अगर आपको कंटेनर एलिमेंट को नेस्ट करना है, तो यह तरीका अहम हो सकता है. ज़्यादा जानकारी के लिए, सीमाओं वाला सेक्शन देखें.
यहां एक उदाहरण दिया गया है, जिसमें कॉन्फ़िगरेशन के ये दोनों विकल्प सेट किए गए हैं:
<responsive-container
name='sidebar'
breakpoints='{"bp4":400,"bp5":500,"bp6":600,"bp7":700,"bp8":800,"bp9":900,"bp10":1000}'>
</responsive-container>
आखिर में, इस कोड का बंडल बनाते समय, पक्का करें कि फ़ीचर डिटेक्शन और डाइनैमिक import()
का इस्तेमाल किया जा रहा हो, ताकि ब्राउज़र कंटेनर क्वेरी के साथ काम नहीं करता हो.
if (!CSS.supports('container-type: inline-size')) {
import('./path/to/responsive-container.js');
}
तीसरा चरण: अपने सीएसएस में फ़ॉलबैक स्टाइल जोड़ना
इस रणनीति का आखिरी चरण, उन ब्राउज़र के लिए फ़ॉलबैक स्टाइल जोड़ना है जो @container
नियमों में तय की गई स्टाइल को नहीं पहचान पाते. <responsive-container>
एलिमेंट पर सेट होने वाली ब्रेकपॉइंट क्लास का इस्तेमाल करके, उन नियमों की डुप्लीकेट कॉपी बनाएं.
पहले के .photo-gallery
उदाहरण के साथ आगे बढ़ते हुए, दो @container
नियमों के लिए फ़ॉलबैक स्टाइल इस तरह दिख सकती है:
/* Container query styles for the `MD` breakpoint. */
@container (min-width: 600px) {
.photo-gallery {
grid-template-columns: 1fr 1fr;
}
}
/* Fallback styles for the `MD` breakpoint. */
@supports not (container-type: inline-size) {
:where(responsive-container.MD) .photo-gallery {
grid-template-columns: 1fr 1fr;
}
}
/* Container query styles for the `XL` breakpoint. */
@container (min-width: 1000px) {
.photo-gallery {
grid-template-columns: 1fr 1fr 1fr;
}
}
/* Fallback styles for the `XL` breakpoint. */
@supports not (container-type: inline-size) {
:where(responsive-container.XL) .photo-gallery {
grid-template-columns: 1fr 1fr 1fr;
}
}
इस कोड में, हर @container
नियम के लिए एक ऐसा नियम है जो शर्त के साथ <responsive-container>
एलिमेंट से मेल खाता है. ऐसा तब होता है, जब इससे जुड़ा ब्रेकपॉइंट क्लास मौजूद हो.
<responsive-container>
एलिमेंट से मेल खाने वाले सिलेक्टर का हिस्सा :where() फ़ंक्शनल स्यूडो-क्लास सिलेक्टर में रैप किया जाता है, ताकि फ़ॉलबैक सिलेक्टर की विशेषता @container
नियम में मूल सिलेक्टर की विशेषता के बराबर रखी जा सके.
हर फ़ॉलबैक नियम को @supports
एलान में भी रैप किया जाता है. हालांकि, फ़ॉलबैक के लिए यह ज़रूरी नहीं है, लेकिन इसका मतलब है कि अगर ब्राउज़र कंटेनर क्वेरी के साथ काम करता है, तो इन नियमों को पूरी तरह से अनदेखा कर देता है. इससे स्टाइल मैचिंग की परफ़ॉर्मेंस बेहतर हो सकती है. अगर ब्राउज़र को पता है कि ब्राउज़र कंटेनर क्वेरी के साथ काम करता है और उसे उन फ़ॉलबैक स्टाइल की ज़रूरत नहीं है, तो यह बिल्ड टूल या सीडीएन को उन एलानों को हटाने की अनुमति देता है.
इस फ़ॉलबैक रणनीति का मुख्य नुकसान यह है कि आपको स्टाइल की जानकारी को दो बार दोहराना पड़ता है. इसमें, उबाऊ और गड़बड़ी की संभावना होती है. हालांकि, अगर सीएसएस प्रीप्रोसेसर का इस्तेमाल किया जा रहा है, तो इसे ऐसे मिक्स में ऐब्स्ट्रैक्ट किया जा सकता है जो आपके लिए @container
नियम और फ़ॉलबैक कोड, दोनों जनरेट करता है. यहां एक उदाहरण दिया गया है, जिसमें Sass का इस्तेमाल किया गया है:
@use 'sass:map';
$breakpoints: (
'SM': 400px,
'MD': 600px,
'LG': 800px,
'XL': 1000px,
);
@mixin breakpoint($breakpoint) {
@container (min-width: #{map.get($breakpoints, $breakpoint)}) {
@content();
}
@supports not (container-type: inline-size) {
:where(responsive-container.#{$breakpoint}) & {
@content();
}
}
}
फिर, यह मिक्सइन होने के बाद, मूल .photo-gallery
कॉम्पोनेंट स्टाइल को कुछ इस तरह से अपडेट किया जा सकता है, जिससे डुप्लिकेशन पूरी तरह खत्म हो जाता है:
.photo-gallery {
display: grid;
grid-template-columns: 1fr;
@include breakpoint('MD') {
grid-template-columns: 1fr 1fr;
}
@include breakpoint('XL') {
grid-template-columns: 1fr 1fr 1fr;
}
}
बस, इतना ही करना है!
रीकैप
इसलिए, याद रखें कि क्रॉस ब्राउज़र फ़ॉलबैक के साथ, कंटेनर क्वेरी का इस्तेमाल करने के लिए, अपने कोड को अपडेट करने का तरीका यहां बताया गया है.
- पहचान वाले कॉम्पोनेंट, जिन्हें आपको उनके कंटेनर के हिसाब से स्टाइल करना है. साथ ही,
@container
नियमों का इस्तेमाल करने के लिए, उनके सीएसएस में@media
नियमों को अपडेट करें. साथ ही (अगर आपने पहले से ऐसा नहीं किया है), तो ब्रेकपॉइंट के नामों के एक सेट के मुताबिक स्टैंडर्ड तय करें, ताकि आपके कंटेनर के नियमों में मौजूद साइज़ की शर्तों को पूरा किया जा सके. - कस्टम
<responsive-container>
एलिमेंट को चलाने वाला JavaScript जोड़ें. इसके बाद, अपने पेज पर कॉन्टेंट एरिया में<responsive-container>
एलिमेंट जोड़ें, ताकि आपके कॉम्पोनेंट काम करें. - पुराने ब्राउज़र के साथ काम करने के लिए, अपने सीएसएस में फ़ॉलबैक स्टाइल जोड़ें. ये उन ब्रेकपॉइंट क्लास से मेल खाते हैं जो आपके एचटीएमएल के
<responsive-container>
एलिमेंट में अपने-आप जुड़ जाते हैं. एक ही स्टाइल को दो बार लिखने से बचने के लिए, सीएसएस प्रीप्रोसेसर मिक्सिन का इस्तेमाल करें.
इस रणनीति की सबसे अच्छी बात यह है कि इसे एक बार में सेटअप किया जा सकता है. हालांकि, इसके बाद नए कॉम्पोनेंट जोड़ने और उनके लिए कंटेनर-रिलेटिव स्टाइल तय करने में ज़्यादा मेहनत नहीं करनी पड़ती.
उदाहरण के तौर पर यह वीडियो दिखता है
ये सभी चरण एक साथ कैसे फ़िट होते हैं, इसे समझने का सबसे अच्छा तरीका हो सकता है कि इसका डेमो देखें.
यह डेमो 2019 में बनाई गई साइट (कंटेनर क्वेरी मौजूद होने से पहले) का अपडेट किया गया वर्शन है. इससे यह समझने में मदद मिलती है कि सही में रिस्पॉन्सिव कॉम्पोनेंट लाइब्रेरी बनाने के लिए कंटेनर क्वेरी क्यों ज़रूरी हैं.
इस साइट में पहले से ही कई "रिस्पॉन्सिव कॉम्पोनेंट" के लिए स्टाइल तय की गई थीं. इसलिए, यहां शुरू की गई रणनीति को किसी गैर-ज़रूरी साइट पर टेस्ट करने के लिए यह बिलकुल सही उम्मीदवार था. शायद, इसे अपडेट करना बेहद आसान था. साथ ही, साइट के मूल स्टाइल में करीब-करीब कोई बदलाव करने की ज़रूरत नहीं थी.
GitHub पर पूरा डेमो सोर्स कोड देखा जा सकता है. साथ ही, फ़ॉलबैक स्टाइल को तय करने का तरीका जानने के लिए, खास तौर पर डेमो कॉम्पोनेंट सीएसएस को देखना न भूलें. अगर आपको सिर्फ़ फ़ॉलबैक के तरीके की जांच करनी है, तो एक फ़ॉलबैक-ओनली डेमो उपलब्ध है, जिसमें सिर्फ़ वही वैरिएंट शामिल है—यहां तक कि कंटेनर क्वेरी के साथ काम करने वाले ब्राउज़र में भी.
सीमाएं और संभावित सुधार
जैसा कि इस पोस्ट की शुरुआत में बताया गया है, यहां बताई गई रणनीति, इस्तेमाल के ज़्यादातर मामलों में उन मामलों के लिए सही काम करती है जिनका ध्यान डेवलपर को कंटेनर क्वेरी के लिए है.
हालांकि, इस्तेमाल के कुछ बेहतर बेहतर उदाहरण यहां दिए गए हैं, जिनमें यह रणनीति जान-बूझकर सपोर्ट करने की कोशिश नहीं करती है. इसके बारे में आगे बताया गया है:
कंटेनर की क्वेरी यूनिट
कंटेनर क्वेरी की खास जानकारी से कई नई यूनिट के बारे में पता चलता है, जो कंटेनर के साइज़ के हिसाब से होती हैं. हालांकि, कुछ मामलों में यह फ़ायदेमंद हो सकता है, लेकिन ज़्यादातर रिस्पॉन्सिव डिज़ाइन मौजूदा तरीकों, जैसे कि प्रतिशत या ग्रिड या फ़्लेक्स लेआउट का इस्तेमाल करके हासिल किए जा सकते हैं.
हालांकि, अगर आपको कंटेनर क्वेरी यूनिट का इस्तेमाल करने की ज़रूरत है, तो कस्टम प्रॉपर्टी का इस्तेमाल करके आसानी से उनके लिए सहायता जोड़ी जा सकती है. खास तौर पर, कंटेनर एलिमेंट पर इस्तेमाल की गई हर यूनिट के लिए कस्टम प्रॉपर्टी तय करके, इस तरह से:
responsive-container {
--cqw: 1cqw;
--cqh: 1cqh;
}
इसके बाद, जब भी आपको कंटेनर क्वेरी यूनिट को ऐक्सेस करने की ज़रूरत हो, यूनिट का इस्तेमाल करने के बजाय उन प्रॉपर्टी का इस्तेमाल करें:
.photo-gallery {
font-size: calc(10 * var(--cqw));
}
इसके बाद, पुराने ब्राउज़र के साथ काम करने के लिए, ResizeObserver
कॉलबैक में मौजूद कंटेनर एलिमेंट पर, उन कस्टम प्रॉपर्टी की वैल्यू सेट करें.
class ResponsiveContainer extends HTMLElement {
// ...
updateBreakpoints(contentRect) {
this.style.setProperty('--cqw', `${contentRect.width / 100}px`);
this.style.setProperty('--cqh', `${contentRect.height / 100}px`);
// ...
}
}
इससे आप असरदार तरीके से "पास" हो सकते हैं और फिर उन्हें ज़रूरत के मुताबिक उनमें बदलाव करने के लिए, आपके पास सीएसएस (उदाहरण के लिए, calc()
, min()
, max()
, clamp()
) का पूरा अधिकार होता है.
लॉजिकल प्रॉपर्टी और राइटिंग मोड सपोर्ट
आपने शायद इनमें से कुछ सीएसएस के उदाहरणों में, @container
एलानों में width
के बजाय inline-size
के इस्तेमाल को देखा होगा. आपने शायद नई cqi
और cqb
यूनिट भी देखी होंगी (इनलाइन और ब्लॉक साइज़ के लिए). इन नई सुविधाओं से यह पता चलता है कि सीएसएस ने फ़िज़िकल या डायरेक्शनल प्रॉपर्टी के बजाय, लॉजिकल प्रॉपर्टी और वैल्यू पर स्विच किया है.
माफ़ करें, Resize Observer जैसे एपीआई अब भी width
और height
में वैल्यू रिपोर्ट करते हैं. इसलिए, अगर आपके डिज़ाइन में लॉजिकल प्रॉपर्टी के हिसाब से बदलाव करने की ज़रूरत है, तो आपको यह खुद ही पता करना होगा.
कंटेनर एलिमेंट में getComputedStyle()
पास करने जैसी किसी सुविधा का इस्तेमाल करके राइटिंग मोड हासिल किया जा सकता है. हालांकि, ऐसा करने के लिए एक शुल्क देना होगा. हालांकि, यह पता लगाने का कोई अच्छा तरीका नहीं है कि राइटिंग मोड बदल रहा है या नहीं.
इस वजह से, <responsive-container>
एलिमेंट के लिए सबसे अच्छा तरीका यह है कि वह राइटिंग मोड वाली ऐसी प्रॉपर्टी को स्वीकार करे जिसे साइट का मालिक ज़रूरत के हिसाब से सेट और अपडेट कर सके. इसे लागू करने के लिए, आपको पिछले सेक्शन में बताए गए तरीके को अपनाना होगा. साथ ही, ज़रूरत के मुताबिक width
और height
को स्वैप करना होगा.
नेस्ट किए गए कंटेनर
container-name
प्रॉपर्टी की मदद से, आप कंटेनर को एक नाम दे सकते हैं, जिसका रेफ़रंस आप @container
नियम में दे सकते हैं. नाम वाले कंटेनर तब काम आते हैं, जब आपके कंटेनर में कंटेनर नेस्ट किए गए हों और आपको सिर्फ़ कुछ कंटेनर से मैच करने के लिए कुछ खास नियमों की ज़रूरत हो (न कि सिर्फ़ सबसे नज़दीकी एंसेस्टर कंटेनर).
यहां बताई गई फ़ॉलबैक रणनीति, कुछ ब्रेकपॉइंट क्लास से मेल खाने वाले एलिमेंट को स्टाइल करने के लिए डिसेंडेंट कॉम्बिनेटर का इस्तेमाल करती है. अगर आपके पास नेस्ट किए गए कंटेनर हैं, तो यह ब्रेक हो सकता है, क्योंकि एक से ज़्यादा कंटेनर एलिमेंट के ऐन्सेस्टर की कोई भी ब्रेकपॉइंट क्लास एक ही समय में दिए गए कॉम्पोनेंट से मैच कर सकती है.
उदाहरण के लिए, यहां .photo-gallery
कॉम्पोनेंट को रैप करने वाले दो <responsive-container>
एलिमेंट दिए गए हैं, लेकिन आउटर कंटेनर, इनर कंटेनर से बड़ा है, इसलिए उसमें अलग-अलग ब्रेकपॉइंट क्लास जोड़ी गई हैं.
<responsive-container class="SM MD LG">
...
<responsive-container class="SM">
...
<div class="photo-gallery">...</div class="photo-gallery">
</responsive-container>
</responsive-container>
इस उदाहरण में, आउटर कंटेनर पर मौजूद MD
और LG
क्लास, .photo-gallery
कॉम्पोनेंट से मिलते-जुलते स्टाइल के नियमों पर असर डालेगी. ये नियम, कंटेनर क्वेरी के व्यवहार से मैच नहीं करते. ऐसा इसलिए है, क्योंकि ये सिर्फ़ सबसे नज़दीकी एंसेस्टर कंटेनर से मैच करते हैं.
इससे बचने के लिए, इनमें से कोई एक तरीका अपनाएं:
- पक्का करें कि आप हमेशा ऐसे किसी भी कंटेनर को नाम दें जिसे आप नेस्ट कर रहे हैं और फिर पक्का करें कि टकराव से बचने के लिए आपके ब्रेकपॉइंट क्लास को उस कंटेनर के नाम के साथ जोड़ा गया हो.
- अपने फ़ॉलबैक सिलेक्टर में, डिसेंडेंट कॉम्बिनेटर के बजाय, चाइल्ड कॉम्बिनेटर का इस्तेमाल करें. यह तरीका थोड़ा ज़्यादा सटीक होता है.
डेमो साइट के नेस्ट किए गए कंटेनर सेक्शन में, नाम वाले कंटेनर इस्तेमाल करके इस तरह के काम करने का एक उदाहरण दिया गया है. साथ ही, कोड में Sass Mixin का इस्तेमाल किया गया है, ताकि नाम वाले और बिना नाम वाले @container
नियमों के लिए फ़ॉलबैक स्टाइल जनरेट की जा सकें.
ऐसे ब्राउज़र का क्या होगा जो :where()
, कस्टम एलिमेंट या रीसाइज़ ऑब्ज़र्वर के साथ काम नहीं करते?
भले ही ये एपीआई नए लग रहे हों, लेकिन ये सभी तीन साल से ज़्यादा समय से सभी ब्राउज़र पर काम करते हों. साथ ही, ये सभी बेसलाइन का बड़े पैमाने पर उपलब्ध हैं.
इसलिए, अगर आपकी साइट पर आने वाले लोगों का एक बड़ा हिस्सा ऐसे ब्राउज़र का इस्तेमाल करता है जिस पर इनमें से किसी भी सुविधा का इस्तेमाल नहीं किया जाता, तो तब तक बिना किसी फ़ॉलबैक के आसानी से उनका इस्तेमाल न किया जा सकता है.
इसके बाद भी, इस्तेमाल के इस खास मामले में, सबसे खराब स्थिति यह हो सकती है कि फ़ॉलबैक आपके कुछ उपयोगकर्ताओं के लिए काम नहीं करेगा. इसका मतलब है कि उन्हें कंटेनर के साइज़ के लिए ऑप्टिमाइज़ किए गए व्यू के बजाय, डिफ़ॉल्ट व्यू दिखेगा.
साइट की फ़ंक्शनलिटी अब भी काम करनी चाहिए और यह वाकई में मायने रखता है.
क्यों न सिर्फ़ कंटेनर क्वेरी पॉलीफ़िल का इस्तेमाल किया जाए?
सीएसएस की सुविधाओं को पॉलीफ़िल करना बेहद मुश्किल है. आम तौर पर, इनके लिए JavaScript में ब्राउज़र के पूरे सीएसएस पार्सर और कैस्केड लॉजिक को फिर से लागू करना पड़ता है. इस वजह से, सीएसएस पॉलीफ़िल के लेखकों को कई बदलाव करने पड़ते हैं. इनमें सुविधाओं की कई सीमाएं और अहम परफ़ॉर्मेंस ओवरहेड होती हैं.
इन वजहों से, हम आम तौर पर प्रोडक्शन में सीएसएस पॉलीफ़िल का इस्तेमाल करने का सुझाव नहीं देते हैं. इसमें Google Chrome Labs से container-query-polyfill भी शामिल है, जो अब रखरखाव नहीं किया जाता और इसे मुख्य रूप से डेमो के लिए बनाया गया था.
यहां बताई गई फ़ॉलबैक रणनीति में कम सीमाएं हैं और इसके लिए बहुत कम कोड की ज़रूरत होती है. साथ ही, यह किसी भी कंटेनर क्वेरी पॉलीफ़िल की तुलना में बेहतर परफ़ॉर्म करेगी.
क्या आपको पुराने ब्राउज़र के लिए भी फ़ॉलबैक लागू करने की ज़रूरत है?
अगर आप यहां बताई गई किसी भी सीमा को लेकर परेशान हैं, तो खुद से यह सवाल पूछना सही रहेगा कि क्या आपको पहले ही फ़ॉलबैक लागू करने की ज़रूरत है. आखिरकार, इन सीमाओं से बचने का सबसे आसान तरीका यह है कि आप बिना किसी फ़ॉलबैक के सुविधा का इस्तेमाल करें. सच कहूं, तो कई मामलों में यह एक सही विकल्प हो सकता है.
caniuse.com के मुताबिक, कंटेनर क्वेरी दुनिया भर के 90% इंटरनेट उपयोगकर्ताओं के लिए काम करती हैं. साथ ही, इस पोस्ट को पढ़ने वाले कई लोगों के हिसाब से, उनके उपयोगकर्ताओं के लिए यह संख्या काफ़ी ज़्यादा हो सकती है. इसलिए, यह ध्यान रखना ज़रूरी है कि आपके ज़्यादातर उपयोगकर्ताओं को आपके यूज़र इंटरफ़ेस (यूआई) का कंटेनर-क्वेरी वर्शन दिखेगा. इनमें से 10% उपयोगकर्ता इसका अनुभव नहीं कर पाएंगे. इस रणनीति का इस्तेमाल करते समय, सबसे खराब स्थिति में, इन उपयोगकर्ताओं को डिफ़ॉल्ट या "मोबाइल" दिखेगा कुछ कॉम्पोनेंट के लिए लेआउट बनाना अभी बाकी नहीं है.
शर्तों में बदलाव करते समय, अपने ज़्यादातर उपयोगकर्ताओं के लिए ऑप्टिमाइज़ करना बेहतर होता है—न कि डिफ़ॉल्ट रूप से सबसे कम-सामान्य-संभावना वाला तरीका अपनाना चाहिए, जिससे सभी उपयोगकर्ताओं को एक जैसा, लेकिन सब जैसा अनुभव मिले.
इसलिए, इससे पहले कि आप यह मान लें कि ब्राउज़र पर काम करने की सुविधा की कमी की वजह से, कंटेनर क्वेरी का इस्तेमाल नहीं किया जा सकता. हालांकि, कुछ समय निकालकर यह सोचें कि अगर आपने इन्हें अपनाने का विकल्प चुना, तो अनुभव कैसा होगा. हालांकि, इसमें कोई बदलाव नहीं किया जा सकता, भले ही इसमें किसी भी तरह की कोई कमी न आए.
आगे की तैयारी
उम्मीद है कि इस पोस्ट से आपको यह भरोसा हो गया है कि अब प्रोडक्शन में कंटेनर क्वेरी का इस्तेमाल किया जा सकता है. साथ ही, आपको कई साल तक इंतज़ार करने की ज़रूरत नहीं है, क्योंकि इसके साथ काम न करने वाले सभी ब्राउज़र पूरी तरह से गायब हो जाते हैं.
हालांकि यहां बताई गई रणनीति के लिए कुछ अतिरिक्त काम करने की ज़रूरत होती है, लेकिन इसे इतना सरल और सरल होना चाहिए कि ज़्यादातर लोग इसे अपनी साइटों पर अपना सकें. हालांकि, इसे अपनाना और भी आसान बनाने की गुंजाइश है. एक आइडिया यह हो सकता है कि किसी खास फ़्रेमवर्क या स्टैक के लिए ऑप्टिमाइज़ किए गए कई अलग-अलग हिस्सों को एक कॉम्पोनेंट में इकट्ठा किया जाए, जो आपके सभी ग्लू को मैनेज करता है. अगर आपका बनाया हुआ कुछ ऐसा है, तो हमें बताएं. हम इसका प्रमोशन करने में आपकी मदद कर सकते हैं!
कंटेनर क्वेरी के अलावा, कई ऐसी शानदार CSS और यूज़र इंटरफ़ेस (यूआई) सुविधाएं हैं जिनका इस्तेमाल अब सभी बड़े ब्राउज़र इंजन के साथ किया जा सकता है. एक समुदाय के रूप में, आइए पता लगाएं कि अब हम उन सुविधाओं का असल में कैसे इस्तेमाल कर सकते हैं, ताकि हमारे उपयोगकर्ताओं को फ़ायदा हो.
अपडेट (25 जुलाई, 2024): मूल रूप से "पहला चरण" में दिए गए दिशा-निर्देश यह सुझाव दिया गया कि मीडिया क्वेरी और कंटेनर क्वेरी एक ही साइज़ की शर्तों का इस्तेमाल कर सकती हैं. यह अक्सर सही होता है, लेकिन हमेशा नहीं (क्योंकि कुछ वजहों के बारे में साफ़ तौर पर बताया गया है). अपडेट किए गए दिशा-निर्देशों में इसकी जानकारी दी गई है. साथ ही, इसमें ऐसे मामलों के उदाहरण भी शामिल किए गए हैं जिनमें साइज़ की शर्तों को बदलने की ज़रूरत हो सकती है.
अपडेट (2 जुलाई, 2024): मूल रूप से, सीएसएस कोड के सभी उदाहरणों में Sass का इस्तेमाल किया गया है. ऐसा इसलिए किया गया है, ताकि आखिरी सुझाव के साथ तालमेल बनाया जा सके. लोगों से मिले सुझाव के आधार पर, शुरुआती कुछ सीएसएस को सामान्य सीएसएस में अपडेट किया गया है. साथ ही, Sass का इस्तेमाल सिर्फ़ ऐसे कोड सैंपल में किया जाता है जिनके लिए मिक्सिन का इस्तेमाल करना ज़रूरी है.