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

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

David Darnes
David Darnes

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

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

हमारे वेब कॉम्पोनेंट बनाने के लिए, हम Lit का इस्तेमाल करते हैं. यह एक लाइब्रेरी है, जो कई बॉयलरप्लेट कोड उपलब्ध कराती है. जैसे, स्टेट, स्कोप की गई स्टाइल, टेंप्लेटिंग वगैरह. 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 की मदद से लिखा गया वेब कॉम्पोनेंट.

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

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

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

DevTools में शैडो डीओएम की जांच की गई.
इस इमेज में, सामान्य टेक्स्ट इनपुट एलिमेंट और हमारे 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="T>itl<e"
  >!<-- ... --
/nord>-t<ab-gr>oup

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>
हमारे डिवाइडर कॉम्पोनेंट के दो इंस्टेंस, जिन्हें दो अलग-अलग रंगों में दिखाना है. एक सेक्शन में नेस्ट किया गया है. इसका इस्तेमाल ज़्यादा सटीक सिलेक्टर के लिए किया जा सकता है. हालांकि, हमें खास तौर पर डिवाइडर को टारगेट करना होगा.

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

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

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



: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 पर टैग करें. आपको Twitter पर Nordhealth @NordhealthHQ भी मिल सकता है. साथ ही, मेरी टीम के अन्य सदस्यों को भी फ़ॉलो किया जा सकता है. इन सदस्यों ने इस डिज़ाइन सिस्टम को तैयार करने और इस लेख में बताई गई सुविधाओं को लागू करने के लिए काफ़ी मेहनत की है: @Viljamis, @WickyNilliams, और @eric_habich.

हीरो इमेज का क्रेडिट: Dan Cristian Pădureț