कंटेनर क्वेरी को अभी इस्तेमाल करने का तरीका

हाल ही में, क्रिस कॉयर ने एक ब्लॉग पोस्ट लिखा. इसमें यह सवाल पूछा गया:

अब जब कंटेनर क्वेरी सभी ब्राउज़र इंजन में काम करती हैं, तो ज़्यादा डेवलपर उनका इस्तेमाल क्यों नहीं कर रहे?

क्रिस की पोस्ट में कई संभावित वजहों के बारे में बताया गया है. उदाहरण के लिए, जागरूकता की कमी, पुरानी आदतें मुश्किल से खत्म हो सकती हैं. हालांकि, इसकी एक खास वजह सबसे अलग है.

कुछ डेवलपर का कहना है कि वे अब कंटेनर क्वेरी का इस्तेमाल करना चाहते हैं, लेकिन उन्हें लगता है कि वे ऐसा नहीं कर पाएंगे क्योंकि अब भी उन्हें पुराने ब्राउज़र के साथ काम करना है.

जैसा कि आपने शीर्षक से अनुमान लगा लिया होगा, हमें लगता है कि ज़्यादातर डेवलपर अब प्रोडक्शन में कंटेनर क्वेरी का इस्तेमाल कर सकते हैं—भले ही, आपको पुराने ब्राउज़र का इस्तेमाल करना क्यों न हो. इस पोस्ट में, आपको ऐसा करने का सुझाव दिया गया है.

व्यावहारिक अप्रोच

अगर आपको अभी अपने कोड में कंटेनर क्वेरी का इस्तेमाल करना है, लेकिन आपको सभी ब्राउज़र में अनुभव एक जैसा दिखाना है, तो उन ब्राउज़र के लिए JavaScript पर आधारित फ़ॉलबैक लागू करें जो कंटेनर क्वेरी के साथ काम नहीं करते हैं.

अब सवाल यह उठता है कि: फ़ॉलबैक कितना पूरा होना चाहिए?

किसी भी दूसरे कार्यक्रम की तरह, इस प्लैटफ़ॉर्म पर भी वीडियो की उपयोगिता और परफ़ॉर्मेंस के बीच अच्छा संतुलन बनाना ही चुनौती है. सीएसएस की सुविधाओं के लिए, अक्सर पूरे एपीआई को इस्तेमाल करना नामुमकिन होता है (पॉलीफ़िल का इस्तेमाल क्यों नहीं करें) देखें. हालांकि, फ़ंक्शन के उस मुख्य सेट की पहचान करके काफ़ी आगे जाया जा सकता है जिसका इस्तेमाल ज़्यादातर डेवलपर करना चाहते हैं. इसके बाद, उन सुविधाओं के लिए फ़ॉलबैक को ऑप्टिमाइज़ किया जा सकता है.

हालांकि, ज़्यादातर डेवलपर कंटेनर क्वेरी के लिए "काम करने के तरीके का मुख्य सेट" क्या चाहते हैं? इस सवाल का जवाब देने के लिए, यह देखें कि फ़िलहाल ज़्यादातर डेवलपर मीडिया क्वेरी के साथ रिस्पॉन्सिव साइटें कैसे बनाते हैं.

ज़्यादातर आधुनिक डिज़ाइन सिस्टम और कॉम्पोनेंट लाइब्रेरी, मोबाइल को ध्यान में रखकर बनाई गई नीतियों के हिसाब से बनाई गई हैं. इन्हें पहले से तय ब्रेकपॉइंट (जैसे कि SM, MD, LG, XL) का इस्तेमाल करके लागू किया गया है. कॉम्पोनेंट, डिफ़ॉल्ट रूप से छोटी स्क्रीन पर अच्छी तरह से दिखने के लिए ऑप्टिमाइज़ किए जाते हैं. इसके बाद, बड़ी स्क्रीन की चौड़ाई के हिसाब से स्टाइल सेट किए जाते हैं. (इसके उदाहरण देखने के लिए, बूटस्ट्रैप और Tailwind दस्तावेज़ देखें.)

यह तरीका कंटेनर-आधारित डिज़ाइन सिस्टम के लिए भी उतना ही कारगर है, जितना कि व्यूपोर्ट-आधारित डिज़ाइन सिस्टम के लिए है. ज़्यादातर मामलों में, डिज़ाइनर के लिए यह ज़रूरी नहीं कि स्क्रीन या व्यूपोर्ट कितना बड़ा है. यह बात यह है कि कॉम्पोनेंट के लिए कितनी जगह उपलब्ध है. दूसरे शब्दों में, ब्रेकपॉइंट पूरे व्यूपोर्ट (और पूरे पेज पर लागू) के मुताबिक होने के बजाय, ब्रेकपॉइंट, साइडबार, मॉडल डायलॉग या पोस्ट बॉडी जैसे खास कॉन्टेंट एरिया पर लागू होंगे.

अगर आपको मोबाइल-फ़र्स्ट, ब्रेकपॉइंट पर आधारित तरीके (जो ज़्यादातर डेवलपर फ़िलहाल इस्तेमाल करते हैं) की सीमाओं के अंदर काम करने में परेशानी हो रही है, तो उस तरीके के लिए कंटेनर-आधारित फ़ॉलबैक लागू करना, हर एक कंटेनर क्वेरी सुविधा के लिए पूरा सहायता लागू करने की तुलना में बहुत आसान है.

अगले सेक्शन में यह बताया गया है कि ये सब कैसे काम करते हैं. साथ ही, सिलसिलेवार निर्देशों की मदद से यह भी बताया गया है कि किसी मौजूदा साइट पर इन्हें कैसे लागू किया जा सकता है.

स्पेस कैसे काम करता है

पहला चरण: @media नियमों के बजाय @container नियमों का इस्तेमाल करने के लिए, कॉम्पोनेंट स्टाइल अपडेट करना

इस पहले चरण में, अपनी साइट पर मौजूद ऐसे किसी भी कॉम्पोनेंट की पहचान करें जिसके बारे में आपको लगता है कि व्यूपोर्ट के मुताबिक साइज़ के बजाय कंटेनर के आधार पर साइज़ बदलने से फ़ायदा होगा.

यह जानने के लिए कि यह रणनीति कैसे काम करती है, सिर्फ़ एक या दो कॉम्पोनेंट के साथ शुरुआत करना अच्छा रहता है. हालांकि, अगर आपको अपने 100% कॉम्पोनेंट को कंटेनर-आधारित स्टाइल में बदलना है, तो भी कोई बात नहीं! इस रणनीति की सबसे अच्छी बात यह है कि ज़रूरत पड़ने पर इसे बढ़ाया भी जा सकता है.

जिन कॉम्पोनेंट को अपडेट करना है उनकी पहचान करने के बाद, आपको उन कॉम्पोनेंट के सीएसएस में हर @media नियम को बदलकर @container नियम करना होगा. साइज़ की शर्तों को एक जैसा रखा जा सकता है.

अगर आपकी सीएसएस में पहले से ही पहले से तय ब्रेकपॉइंट का इस्तेमाल किया जा रहा है, तो उन ब्रेकपॉइंट का ठीक तरह से इस्तेमाल किया जा सकता है. अगर पहले से तय ब्रेकपॉइंट का इस्तेमाल नहीं किया जा रहा है, तो आपको उनके लिए नाम तय करने होंगे. इसके बारे में बाद में JavaScript में बताया जाएगा. इसके लिए, दूसरा चरण देखें).

यहां .photo-gallery कॉम्पोनेंट के लिए स्टाइल का एक उदाहरण दिया गया है. यह डिफ़ॉल्ट रूप से एक सिंगल कॉलम होता है. इसके बाद, यह MD और XL ब्रेकपॉइंट में दो और तीन कॉलम में बदलने के लिए, अपनी स्टाइल को अपडेट करता है (कम से कम):

.photo-gallery {
  display: grid;
  grid-template-columns: 1fr;
}

/* Styles for the `MD` breakpoint */
@media (min-width: 768px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Styles for the `XL` breakpoint */
@media (min-width: 1280px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

इन कॉम्पोनेंट स्टाइल को @media नियमों से बदलकर @container नियमों का इस्तेमाल करने के लिए, अपने कोड में ढूंढें और बदलें:

/* Before: */
@media (min-width: 768px) { /* ... */ }
@media (min-width: 1280px) { /* ... */ }

/* After: */
@container (min-width: 768px) { /* ... */ }
@container (min-width: 1280px) { /* ... */ }

अपने कॉम्पोनेंट के स्टाइल को @media नियमों से ब्रेकपॉइंट पर आधारित @container नियमों में अपडेट करने के बाद, अगले चरण में अपने कंटेनर एलिमेंट कॉन्फ़िगर करें.

दूसरा चरण: अपने एचटीएमएल में कंटेनर एलिमेंट जोड़ना

पिछले चरण में तय किए गए कॉम्पोनेंट के स्टाइल, जो कंटेनर एलिमेंट के साइज़ पर आधारित होते हैं. अगले चरण में यह तय किया जाता है कि आपके पेज पर कौनसे एलिमेंट ऐसे कंटेनर एलिमेंट होने चाहिए जिनके साइज़ के हिसाब से @container नियम तय होंगे.

सीएसएस में किसी भी एलिमेंट को कंटेनर एलिमेंट माना जा सकता है. इसके लिए, container-type प्रॉपर्टी को size या inline-size पर सेट करें. अगर आपके कंटेनर के नियम चौड़ाई पर आधारित हैं, तो आम तौर पर inline-size का इस्तेमाल करना है.

इस बेसिक एचटीएमएल स्ट्रक्चर वाली साइट का इस्तेमाल करें:

<body>
  <div class="sidebar">...</div>
  <div class="content">...</div>
</body>

इस साइट पर .sidebar और .content एलिमेंट का containers बनाने के लिए, अपनी सीएसएस में यह नियम जोड़ें:

.content, .sidebar {
  container-type: inline-size;
}

कंटेनर क्वेरी के साथ काम करने वाले ब्राउज़र के लिए, आपको पिछले चरण में तय की गई कॉम्पोनेंट स्टाइल को मुख्य कॉन्टेंट एरिया या साइडबार के हिसाब से बनाना होता है. यह इस बात पर निर्भर करता है कि वे किस एलिमेंट में मौजूद हैं.

हालांकि, कंटेनर क्वेरी का समर्थन न करने वाले ब्राउज़र के लिए, कुछ अतिरिक्त काम करना होता है.

आपको कोई ऐसा कोड जोड़ना होगा जो कंटेनर एलिमेंट के साइज़ में बदलाव का पता लगा सके और फिर उन बदलावों के आधार पर डीओएम को इस तरह अपडेट करे कि आपका सीएसएस हुक कर सके.

अच्छी बात यह है कि इस काम के लिए ज़रूरी कोड बहुत कम है. इसे एक ऐसे कॉम्पोनेंट के तौर पर दिखाया जा सकता है जिसे शेयर किया गया हो. इसका इस्तेमाल किसी भी साइट और कॉन्टेंट एरिया में किया जा सकता है.

यह कोड, फिर से इस्तेमाल किए जा सकने वाले <responsive-container> एलिमेंट के बारे में बताता है. यह साइज़ में होने वाले बदलावों को अपने-आप सुनता है. साथ ही, उन ब्रेकपॉइंट क्लास को जोड़ता है जिन्हें आपकी सीएसएस, इन चीज़ों के आधार पर स्टाइल कर सकती है:

// A mapping of default breakpoint class names and min-width sizes.
// Redefine these as needed based on your site's design.
const defaultBreakpoints = {SM: 512, MD: 768, LG: 1024, XL: 1280};

// 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 768 से 1024 पिक्सल (कोड में सेट की गई डिफ़ॉल्ट ब्रेकपॉइंट वैल्यू के आधार पर) के बीच है, तो 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='{"bp1":500,"bp2":1000,"bp3":1500}'>
</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: 768px) {
  .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: 1280px) {
  .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': 512px,
  'MD': 576px,
  'LG': 1024px,
  'XL': 1280px,
);

@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;
  }
}

बस, इतना ही करना है!

Recap

इसलिए, याद रखें कि क्रॉस ब्राउज़र फ़ॉलबैक के साथ, कंटेनर क्वेरी का इस्तेमाल करने के लिए, अपने कोड को अपडेट करने का तरीका यहां बताया गया है.

  1. पहचान वाले कॉम्पोनेंट, जिन्हें आपको उनके कंटेनर के हिसाब से स्टाइल करना है. साथ ही, @container नियमों का इस्तेमाल करने के लिए, उनके सीएसएस में @media नियमों को अपडेट करें. साथ ही (अगर आपने पहले से ऐसा नहीं किया है), तो ब्रेकपॉइंट के नामों के एक सेट के मुताबिक स्टैंडर्ड तय करें, ताकि आपके कंटेनर के नियमों में मौजूद साइज़ की शर्तों को पूरा किया जा सके.
  2. कस्टम <responsive-container> एलिमेंट को चलाने वाला JavaScript जोड़ें. इसके बाद, अपने पेज पर कॉन्टेंट एरिया में <responsive-container> एलिमेंट जोड़ें, ताकि आपके कॉम्पोनेंट काम करें.
  3. पुराने ब्राउज़र के साथ काम करने के लिए, अपने सीएसएस में फ़ॉलबैक स्टाइल जोड़ें. ये उन ब्रेकपॉइंट क्लास से मेल खाते हैं जो आपके एचटीएमएल के <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`);

    // ...
  }
}

इससे आपको उन वैल्यू को JavaScript से सीएसएस में "पास" करने की सुविधा मिलती है. इसके बाद, आपके पास सीएसएस का पूरा अधिकार होता है कि वह ज़रूरत के हिसाब से उनमें बदलाव कर सके. उदाहरण के लिए, 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 कॉम्पोनेंट से मिलते-जुलते स्टाइल के नियमों पर असर डालेगी. ये नियम, कंटेनर क्वेरी के व्यवहार से मैच नहीं करते. ऐसा इसलिए है, क्योंकि ये सिर्फ़ सबसे नज़दीकी एंसेस्टर कंटेनर से मैच करते हैं.

इससे बचने के लिए, इनमें से कोई एक तरीका अपनाएं:

  1. पक्का करें कि आप हमेशा ऐसे किसी भी कंटेनर को नाम दें जिसे आप नेस्ट कर रहे हैं और फिर पक्का करें कि टकराव से बचने के लिए आपके ब्रेकपॉइंट क्लास को उस कंटेनर के नाम के साथ जोड़ा गया हो.
  2. अपने फ़ॉलबैक सिलेक्टर में, डिसेंडेंट कॉम्बिनेटर के बजाय, चाइल्ड कॉम्बिनेटर का इस्तेमाल करें. यह तरीका थोड़ा ज़्यादा सटीक होता है.

डेमो साइट के नेस्ट किए गए कंटेनर सेक्शन में, नाम वाले कंटेनर इस्तेमाल करके इस तरह के काम करने का एक उदाहरण दिया गया है. साथ ही, कोड में Sass Mixin का इस्तेमाल किया गया है, ताकि नाम वाले और बिना नाम वाले @container नियमों के लिए फ़ॉलबैक स्टाइल जनरेट की जा सकें.

ऐसे ब्राउज़र का क्या होगा जो :where(), कस्टम एलिमेंट या रीसाइज़ ऑब्ज़र्वर के साथ काम नहीं करते?

भले ही ये एपीआई नए लग रहे हों, लेकिन ये सभी तीन साल से ज़्यादा समय से सभी ब्राउज़र पर काम करते हों. साथ ही, ये सभी बेसलाइन का बड़े पैमाने पर उपलब्ध हैं.

इसलिए, अगर आपकी साइट पर आने वाले लोगों का एक बड़ा हिस्सा ऐसे ब्राउज़र का इस्तेमाल करता है जिस पर इनमें से किसी भी सुविधा का इस्तेमाल नहीं किया जाता, तो तब तक बिना किसी फ़ॉलबैक के आसानी से उनका इस्तेमाल न किया जा सकता है.

इसके बाद भी, इस्तेमाल के इस खास मामले में, सबसे खराब स्थिति यह हो सकती है कि फ़ॉलबैक आपके कुछ उपयोगकर्ताओं के लिए काम नहीं करेगा. इसका मतलब है कि उन्हें कंटेनर के साइज़ के लिए ऑप्टिमाइज़ किए गए व्यू के बजाय, डिफ़ॉल्ट व्यू दिखेगा.

साइट की फ़ंक्शनलिटी अब भी काम करनी चाहिए और यह वाकई में मायने रखता है.

क्यों न सिर्फ़ कंटेनर क्वेरी पॉलीफ़िल का इस्तेमाल किया जाए?

सीएसएस की सुविधाओं को पॉलीफ़िल करना बेहद मुश्किल है. आम तौर पर, इनके लिए JavaScript में ब्राउज़र के पूरे सीएसएस पार्सर और कैस्केड लॉजिक को फिर से लागू करना पड़ता है. इस वजह से, सीएसएस पॉलीफ़िल के लेखकों को कई बदलाव करने पड़ते हैं. इनमें सुविधाओं की कई सीमाएं और अहम परफ़ॉर्मेंस ओवरहेड होती हैं.

इन वजहों से, हम आम तौर पर प्रोडक्शन में सीएसएस पॉलीफ़िल का इस्तेमाल करने का सुझाव नहीं देते हैं. इसमें Google Chrome Labs से container-query-polyfill भी शामिल है, जो अब रखरखाव नहीं किया जाता और इसे मुख्य रूप से डेमो के लिए बनाया गया था.

यहां बताई गई फ़ॉलबैक रणनीति में कम सीमाएं हैं और इसके लिए बहुत कम कोड की ज़रूरत होती है. साथ ही, यह किसी भी कंटेनर क्वेरी पॉलीफ़िल की तुलना में बेहतर परफ़ॉर्म करेगी.

क्या आपको पुराने ब्राउज़र के लिए भी फ़ॉलबैक लागू करने की ज़रूरत है?

अगर आप यहां बताई गई किसी भी सीमा को लेकर परेशान हैं, तो खुद से यह सवाल पूछना सही रहेगा कि क्या आपको पहले ही फ़ॉलबैक लागू करने की ज़रूरत है. आखिरकार, इन सीमाओं से बचने का सबसे आसान तरीका यह है कि आप बिना किसी फ़ॉलबैक के सुविधा का इस्तेमाल करें. सच कहूं, तो कई मामलों में यह एक सही विकल्प हो सकता है.

caniuse.com के मुताबिक, कंटेनर क्वेरी दुनिया भर के 90% इंटरनेट उपयोगकर्ताओं के लिए काम करती हैं. साथ ही, इस पोस्ट को पढ़ने वाले कई लोगों के हिसाब से, उनके उपयोगकर्ताओं के लिए यह संख्या काफ़ी ज़्यादा हो सकती है. इसलिए, यह ध्यान रखना ज़रूरी है कि आपके ज़्यादातर उपयोगकर्ताओं को आपके यूज़र इंटरफ़ेस (यूआई) का कंटेनर-क्वेरी वर्शन दिखेगा. इनमें से 10% उपयोगकर्ता इसका अनुभव नहीं कर पाएंगे. इस रणनीति का इस्तेमाल करते समय, सबसे खराब स्थिति में, इन उपयोगकर्ताओं को कुछ कॉम्पोनेंट के लिए डिफ़ॉल्ट या "मोबाइल" लेआउट दिखेगा. यह सिर्फ़ उन कॉम्पोनेंट के लिए होता है जो दुनिया के आखिरी चरण में नहीं बने हैं.

शर्तों में बदलाव करते समय, अपने ज़्यादातर उपयोगकर्ताओं के लिए ऑप्टिमाइज़ करना बेहतर होता है—न कि डिफ़ॉल्ट रूप से सबसे कम-सामान्य-संभावना वाला तरीका अपनाना चाहिए, जिससे सभी उपयोगकर्ताओं को एक जैसा, लेकिन सब जैसा अनुभव मिले.

इसलिए, इससे पहले कि आप यह मान लें कि ब्राउज़र पर काम करने की सुविधा की कमी की वजह से, कंटेनर क्वेरी का इस्तेमाल नहीं किया जा सकता. हालांकि, कुछ समय निकालकर यह सोचें कि अगर आपने इन्हें अपनाने का विकल्प चुना, तो अनुभव कैसा होगा. हालांकि, इसमें कोई बदलाव नहीं किया जा सकता, भले ही इसमें किसी भी तरह की कोई कमी न आए.

आगे की तैयारी

उम्मीद है कि इस पोस्ट से आपको यह भरोसा हो गया है कि अब प्रोडक्शन में कंटेनर क्वेरी का इस्तेमाल किया जा सकता है. साथ ही, आपको कई साल तक इंतज़ार करने की ज़रूरत नहीं है, क्योंकि इसके साथ काम न करने वाले सभी ब्राउज़र पूरी तरह से गायब हो जाते हैं.

हालांकि यहां बताई गई रणनीति के लिए कुछ अतिरिक्त काम करने की ज़रूरत होती है, लेकिन इसे इतना सरल और सरल होना चाहिए कि ज़्यादातर लोग इसे अपनी साइटों पर अपना सकें. हालांकि, इसे अपनाना और भी आसान बनाने की गुंजाइश है. एक आइडिया यह हो सकता है कि किसी खास फ़्रेमवर्क या स्टैक के लिए ऑप्टिमाइज़ किए गए कई अलग-अलग हिस्सों को एक कॉम्पोनेंट में इकट्ठा किया जाए, जो आपके सभी ग्लू को मैनेज करता है. अगर आपका बनाया हुआ कुछ ऐसा है, तो हमें बताएं. हम इसका प्रमोशन करने में आपकी मदद कर सकते हैं!

कंटेनर क्वेरी के अलावा, कई ऐसी शानदार CSS और यूज़र इंटरफ़ेस (यूआई) सुविधाएं हैं जिनका इस्तेमाल अब सभी बड़े ब्राउज़र इंजन के साथ किया जा सकता है. एक समुदाय के रूप में, आइए पता लगाएं कि अब हम उन सुविधाओं का असल में कैसे इस्तेमाल कर सकते हैं, ताकि हमारे उपयोगकर्ताओं को फ़ायदा हो.