Nordhealth, वेब कॉम्पोनेंट में कस्टम प्रॉपर्टी का इस्तेमाल कैसे करता है

डिज़ाइन सिस्टम और कॉम्पोनेंट लाइब्रेरी में कस्टम प्रॉपर्टी इस्तेमाल करने के फ़ायदे.

David Darnes
David Darnes

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

हम वेब कॉम्पोनेंट कैसे बनाते हैं

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


import {html, css, LitElement} from 'lit';

export class SimpleGreeting extends LitElement {
  static styles = css`:host { color: blue; font-family: sans-serif; }`;

  static properties = {
    name: {type: String},
  };

  constructor() {
    super();
    this.name = 'there';
  }

  render() {
    return html`

Hey ${this.name}, welcome to Web Components!

`
; } } customElements.define('simple-greeting', SimpleGreeting);
Lit की मदद से लिखा गया वेब कॉम्पोनेंट.

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

शैडो डीओएम स्टाइल एनकैप्सुलेशन

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

DevTools में शैडो DOM की जांच की गई.
सामान्य टेक्स्ट इनपुट एलिमेंट और हमारे Nord इनपुट वेब कॉम्पोनेंट में शैडो DOM का उदाहरण.

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

स्टाइल को इस तरह से एनकैप्सुलेट करना, हमारी कॉम्पोनेंट लाइब्रेरी का एक फ़ायदा है. इससे हमें यह गारंटी मिलती है कि जब कोई व्यक्ति हमारे किसी कॉम्पोनेंट का इस्तेमाल करेगा, तो वह वैसा ही दिखेगा जैसा हम चाहते हैं. भले ही, पैरंट पेज पर कोई भी स्टाइल लागू की गई हो. साथ ही, यह पक्का करने के लिए कि ऐसा हो, हम अपने सभी वेब कॉम्पोनेंट के रूट या "होस्ट" में all: unset; जोड़ते हैं.


:host {
  all: unset;
  display: block;
  box-sizing: border-box;
  text-align: start;
  /* ... */
}
शैडो रूट या होस्ट सिलेक्टर पर लागू किए जा रहे कुछ कॉम्पोनेंट के छोटे-मोटे बदलाव वाले कोड.

हालांकि, अगर आपके वेब कॉम्पोनेंट का इस्तेमाल करने वाले किसी व्यक्ति के पास कुछ स्टाइल बदलने की कोई मान्य वजह हो, तो क्या होगा? ऐसा हो सकता है कि टेक्स्ट की किसी लाइन को उसके कॉन्टेक्स्ट की वजह से ज़्यादा कंट्रास्ट की ज़रूरत हो या बॉर्डर को मोटा करना ज़रूरी हो? अगर आपके कॉम्पोनेंट में कोई स्टाइल नहीं डाली जा सकती, तो स्टाइल के विकल्पों को कैसे अनलॉक किया जा सकता है?

ऐसे में, सीएसएस की कस्टम प्रॉपर्टी काम आती हैं.

सीएसएस कस्टम प्रॉपर्टी

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


:root {
  --n-color-accent: rgb(53, 89, 199);
  /* ... */
}

.n-color-accent-text {
  color: var(--n-color-accent);
}
हमारे सीएसएस फ़्रेमवर्क से लिया गया उदाहरण. इसमें डिज़ाइन टोकन को कस्टम प्रॉपर्टी के तौर पर दिखाया गया है और उसे हेल्पर क्लास में इस्तेमाल किया गया है.

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

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

Nord वेब कॉम्पोनेंट में कस्टम प्रॉपर्टी

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


:root {
  --n-space-m: 16px;
  --n-space-l: 24px;
  /* ... */
  --n-color-background: rgb(255, 255, 255);
  --n-color-border: rgb(216, 222, 228);
  /* ... */
}
रूट सिलेक्टर पर तय की जा रही सीएसएस कस्टम प्रॉपर्टी.

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


:host {
  --n-tab-group-padding: 0;
  --n-tab-list-background: var(--n-color-background);
  --n-tab-list-border: inset 0 -1px 0 0 var(--n-color-border);
  /* ... */
}

.n-tab-group-list {
  box-shadow: var(--n-tab-list-border);
  background-color: var(--n-tab-list-background);
  gap: var(--n-space-s);
  /* ... */
}
कस्टम प्रॉपर्टी को कॉम्पोनेंट के शैडो रूट पर तय किया जा रहा है. इसके बाद, कॉम्पोनेंट की स्टाइल में इस्तेमाल किया जा रहा है. डिज़ाइन टोकन की सूची में मौजूद कस्टम प्रॉपर्टी का भी इस्तेमाल किया जा रहा है.

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


.n-tab-group-list::before {
  /* ... */
  padding-inline-start: var(--n-tab-group-padding);
}

.n-tab-group-list::after {
  /* ... */
  padding-inline-end: var(--n-tab-group-padding);
}
टैब ग्रुप की पैडिंग के लिए, कॉन्टेक्स्ट के हिसाब से कस्टम प्रॉपर्टी का इस्तेमाल, कॉम्पोनेंट कोड में कई जगहों पर किया जा रहा है.

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


:host([padding="l"]) {
  --n-tab-group-padding: var(--n-space-l);
}
टैब कॉम्पोनेंट का एक वैरिएशन, जिसमें कई अपडेट के बजाय एक कस्टम प्रॉपर्टी अपडेट का इस्तेमाल करके पैडिंग को बदला जा रहा है.

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


<nord-tab-group label="Title">
  <!-- ... -->
</nord-tab-group>

<style>
  nord-tab-group {
    --n-tab-group-padding: var(--n-space-xl);
  }
</style>
पेज पर टैब ग्रुप कॉम्पोनेंट का इस्तेमाल किया जा रहा है और पैडिंग कस्टम प्रॉपर्टी को बड़े साइज़ में अपडेट किया जा रहा है.

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

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

कस्टम प्रॉपर्टी के बारे में ज़्यादा जानकारी

इस लेख को लिखे जाने के समय, हम अपने दस्तावेज़ में इन कॉन्टेक्स्ट के हिसाब से कस्टम प्रॉपर्टी के बारे में नहीं बताते हैं. हालांकि, हमारा प्लान है कि हम इनके बारे में बताएं, ताकि हमारी बड़ी डेवलपमेंट टीम इन प्रॉपर्टी को समझ सके और इनका फ़ायदा ले सके. हमारे कॉम्पोनेंट, npm पर एक मेनिफ़ेस्ट फ़ाइल के साथ पैकेज किए जाते हैं. इसमें कॉम्पोनेंट के बारे में पूरी जानकारी होती है. इसके बाद, हम मेनिफ़ेस्ट फ़ाइल को डेटा के तौर पर इस्तेमाल करते हैं. ऐसा तब किया जाता है, जब हमारे दस्तावेज़ की साइट को डिप्लॉय किया जाता है. इसके लिए, Eleventy और इसकी ग्लोबल डेटा सुविधा का इस्तेमाल किया जाता है. हम इस मेनिफ़ेस्ट डेटा फ़ाइल में, कॉन्टेक्स्ट के हिसाब से कस्टम प्रॉपर्टी शामिल करने की योजना बना रहे हैं.

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


<nord-divider></nord-divider>

<section>
  <nord-divider></nord-divider>
   <!-- ... -->
</section>

<style>
  nord-divider {
    --n-divider-color: var(--n-color-status-danger);
  }

  section {
    padding: var(--n-space-s);
    background: var(--n-color-surface-raised);
  }
  
  section nord-divider {
    --n-divider-color: var(--n-color-status-success);
  }
</style>
हमारे डिवाइडर कॉम्पोनेंट के दो इंस्टेंस, जिन्हें दो अलग-अलग रंगों की ज़रूरत है. एक को सेक्शन के अंदर नेस्ट किया गया है, जिसका इस्तेमाल हम ज़्यादा सटीक सिलेक्टर के लिए कर सकते हैं. हालांकि, हमें खास तौर पर डिवाइडर को टारगेट करना होगा.

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

निजी और सार्वजनिक कस्टम प्रॉपर्टी

निजी कस्टम प्रॉपर्टी को लिया वेरो ने बनाया है. यह कॉम्पोनेंट पर मौजूद, कॉन्टेक्स्ट के हिसाब से "निजी" कस्टम प्रॉपर्टी होती है. हालांकि, इसे फ़ॉलबैक के साथ "सार्वजनिक" कस्टम प्रॉपर्टी पर सेट किया जाता है.



:host {
  --_n-divider-color: var(--n-divider-color, var(--n-color-border));
  --_n-divider-size: var(--n-divider-size, 1px);
}

.n-divider {
  border-block-start: solid var(--_n-divider-size) var(--_n-divider-color);
  /* ... */
}
डिवाइडर वेब कॉम्पोनेंट सीएसएस, जिसमें कॉन्टेक्स्ट के हिसाब से कस्टम प्रॉपर्टी अडजस्ट की गई हैं, ताकि इंटरनल सीएसएस किसी निजी कस्टम प्रॉपर्टी पर निर्भर रहे. इसे फ़ॉलबैक के साथ सार्वजनिक कस्टम प्रॉपर्टी पर सेट किया गया है.

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


<nord-divider></nord-divider>

<section>
  <nord-divider></nord-divider>
   <!-- ... -->
</section>

<style>
  nord-divider {
    --n-divider-color: var(--n-color-status-danger);
  }

  section {
    padding: var(--n-space-s);
    background: var(--n-color-surface-raised);
    --n-divider-color: var(--n-color-status-success);
  }
</style>
दो डिवाइडर फिर से दिख रहे हैं. हालांकि, इस बार डिवाइडर का रंग बदला जा सकता है. इसके लिए, सेक्शन सिलेक्टर में डिवाइडर की कॉन्टेक्स्ट के हिसाब से कस्टम प्रॉपर्टी जोड़ें. डिवाइडर इसे इनहेरिट करेगा. इससे कोड ज़्यादा व्यवस्थित और फ़्लेक्सिबल बनेगा.

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

हमें उम्मीद है कि आपको यह जानकारी पसंद आई होगी कि हम सीएसएस की कस्टम प्रॉपर्टी के साथ वेब कॉम्पोनेंट का इस्तेमाल कैसे करते हैं. हमें बताएं कि आपको यह वीडियो कैसा लगा. अगर आपको अपने काम में इनमें से कोई तरीका इस्तेमाल करना है, तो मुझसे Twitter पर @DavidDarnes पर संपर्क करें. Nordhealth को Twitter पर @NordhealthHQ पर भी ढूंढा जा सकता है. साथ ही, मेरी टीम के बाकी सदस्यों को भी ढूंढा जा सकता है. उन्होंने इस डिज़ाइन सिस्टम को एक साथ लाने और इस दस्तावेज़ में बताई गई सुविधाओं को लागू करने के लिए कड़ी मेहनत की है: @Viljamis, @WickyNilliams, और @eric_habich.