शैडो डीओएम, स्टाइल की एक सीमा है: पेज के नियम अंदर नहीं आते और कॉम्पोनेंट के नियम बाहर नहीं जाते. हालांकि, इनहेरिट की गई प्रॉपर्टी (इनमें कस्टम प्रॉपर्टी भी शामिल हैं) पर यह बात लागू नहीं होती. नीचे दिए गए चैनलों के ज़रिए, जान-बूझकर इस सीमा को पार करना.
:host, :host(), :host-context()
/* The component's own host element, styled from inside its shadow tree. */
:host { display: block; }
/* Only when the host matches a selector (e.g. a reflected state attribute). */
:host([disabled]) { opacity: 0.5; pointer-events: none; }
/* Based on an ancestor in the Light DOM; useful for theming. */
:host-context([theme="dark"]) { background: #111; color: #eee; }
:host-context() से बचें. यह एंसेस्टर की जांच करने के लिए, बाउंड्री के बाहर पहुंचता है. हालांकि, Firefox और Safari ने इसे शिप करने से मना कर दिया है. साथ ही, CSSWG इसे आगे डेवलप नहीं करना चाहता. इसे Chromium के लिए सिर्फ़ एक डेड एंड के तौर पर देखें, न कि आने वाले समय के विकल्प के तौर पर. इसके बजाय, इनहेरिट की गई सीएसएस कस्टम प्रॉपर्टी (नीचे) के ज़रिए थीम सेट करें: उपभोक्ता, प्रॉपर्टी को पैरंट एलिमेंट पर सेट करता है और कॉम्पोनेंट उसे बाउंड्री के पार पढ़ता है. यह हर जगह काम करता है और दोनों पक्षों को अलग रखता है.
इनहेरिट की गई प्रॉपर्टी और कस्टम प्रॉपर्टी, बाउंड्री को पार करती हैं
इनहेरिट की गई सीएसएस प्रॉपर्टी (color, font-family, line-height, और सीएसएस कस्टम प्रॉपर्टी) शैडो बाउंड्री से पास होती हैं. इससे कस्टम प्रॉपर्टी, मुख्य थीमिंग एपीआई बन जाती हैं: उन्हें सही फ़ॉलबैक के साथ एक्सपोज़ करें.
:host {
/* Consumers override --card-bg from outside; the fallback keeps it usable. */
background: var(--card-bg, white);
color: var(--card-fg, black);
}
:host पर तय की गई कस्टम प्रॉपर्टी को सिर्फ़ उन नियमों से बदला जा सकता है जो खास तौर पर होस्ट एलिमेंट को टारगेट करते हैं. ट्री में कहीं से भी इनहेरिट और ओवरराइड करने के लिए, :host पर सार्वजनिक प्रॉपर्टी को सेट न करें और हर var() में फ़ॉलबैक पर भरोसा करें; :host पर सार्वजनिक प्रॉपर्टी को सीड न करें.
फ़ॉलबैक को हर var() पर दोहराने के बजाय, एक बार एलान करने के लिए, :host पर एक निजी "शैडो" प्रॉपर्टी तय करें. यह प्रॉपर्टी, सार्वजनिक प्रॉपर्टी को पढ़ती है और निजी प्रॉपर्टी को इंटरनल तौर पर रेफ़रंस देती है:
:host {
--_card-bg: var(--card-bg, white);
--_card-fg: var(--card-fg, black);
}
.card { background: var(--_card-bg); color: var(--_card-fg); }
उपभोक्ता अब भी बाहर से --card-bg को बदल सकते हैं; शुरुआत में मौजूद अंडरस्कोर से पता चलता है कि उपनाम इंटरनल है और फ़ॉलबैक सिर्फ़ एक जगह पर मौजूद है.
::slotted(): प्रोजेक्ट किए गए लाइट डीओएम को स्टाइल करना
::slotted(selector), स्लॉट को असाइन किए गए टॉप-लेवल नोड को टारगेट करता है. यह उनके डिसेंडेंट तक नहीं पहुंच सकता. साथ ही, यह किसी भी लाइट डीओएम नियम (उपभोक्ता के पास अपने कॉन्टेंट का मालिकाना हक होता है) के सामने काम नहीं करता. इसलिए, इसका इस्तेमाल सिर्फ़ छोटे-मोटे बदलावों के लिए करें, कंट्रोल करने के लिए नहीं. ::slotted(...) !important, उपभोक्ता के नियमों को बदल सकता है. हालांकि, ऐसा करने से उपभोक्ता को मिलने वाली स्टाइलिंग बदल जाती है. इसलिए, इसका इस्तेमाल स्ट्रक्चर से जुड़ी गड़बड़ियों को ठीक करने के लिए करें, न कि स्टाइलिंग को बदलने के लिए.
/* Matches a slotted <p>, but NOT a <p> nested inside a slotted <div>. */
::slotted(p) { margin: 0; }
::part() और exportparts: थीम के लिए इंटरनल एक्सपोज़ करना
किसी इंटरनल एलिमेंट को part="name" से मार्क करें, ताकि उपभोक्ता आपके इंटरनल स्ट्रक्चर को जाने बिना, उसे किसी भी प्रॉपर्टी के साथ स्टाइल कर सकें.
<!-- inside the shadow template -->
<button part="submit">Submit</button>
/* consumer stylesheet */
my-card::part(submit) { background: navy; color: white; }
कुछ हाई-लेवल पार्ट (बटन, इनपुट, लेबल) को एक्सपोज़ करें, न कि हर <div> को. बड़े पार्ट के एक्सपोज़ होने से, एपीआई के काम न करने का खतरा बढ़ जाता है. अपने कॉम्पोनेंट के ज़रिए, नेस्ट किए गए कॉम्पोनेंट के हिस्सों को फिर से ऊपर की ओर दिखाने के लिए, उन्हें exportparts के साथ फ़ॉरवर्ड करें:
<inner-widget exportparts="submit: card-submit"></inner-widget>
दोनों चैनलों में से सोच-समझकर चुनें: वैल्यू के सीमित और डिज़ाइन-सिस्टम के लिए सुरक्षित सेट के लिए कस्टम प्रॉपर्टी; किसी खास एलिमेंट की स्टाइलिंग के लिए पार्ट.
रैप किए गए नेटिव एलिमेंट पर स्टाइल फ़ॉरवर्ड करना
जब कोई कस्टम एलिमेंट किसी नेटिव कंट्रोल को रैप करता है (जैसे, किसी असल <button> के आस-पास <my-button>), तो आम तौर पर लोगों को तीन चीज़ों से परेशानी होती है:
- फ़ॉर्म कंट्रोल, टाइपोग्राफ़ी को इनहेरिट नहीं करते.
colorऔर कस्टम प्रॉपर्टी, बाउंड्री को पार करती हैं. हालांकि,<button>,<input>, और<select>, UA स्टाइलशीट सेfontऔर अन्य प्रॉपर्टी लेते हैं. यह स्टाइलशीट, इनहेरिट नहीं होती. इसलिए, रैप किया गया कंट्रोल, पेज के फ़ॉन्ट के बजाय प्लैटफ़ॉर्म के फ़ॉन्ट में रेंडर होता है. ऐसा तब तक होता है, जब तक शैडो ट्री मेंfont: inherit(और आम तौर परcolor: inherit) सेट नहीं किया जाता. यह सबसे आम गलती है. :hostस्टाइल, इनर एलिमेंट पर लागू नहीं होती हैं.:hostपरbackground/border/paddingसेट करने से, होस्ट बॉक्स को स्टाइल किया जाता है, न कि उसके अंदर मौजूद कंट्रोल को. जान-बूझकर फ़ॉरवर्ड करना: ओपन-एंडेड स्टाइलिंग के लिए, कंट्रोल को::partके तौर पर एक्सपोज़ करें या कस्टम प्रॉपर्टी के ज़रिए वैल्यू के तय सेट को पाइप करें —:hostनियम, रैप किए गए एलिमेंट में कैस्केड नहीं होता.display: contents+all: inheritएक असल समझौता है, न कि कोई शॉर्टकट.display: contentsका इस्तेमाल करके होस्ट को छोटा करना औरall: inheritका इस्तेमाल करके इनर कंट्रोल को रीसेट करना, फ़िलहाल रैप किए गए नेटिव एलिमेंट में आर्बिट्रेरी स्टाइल पास करने का एकमात्र सामान्य तरीका है. इसके लिए, उपभोक्ताओं को हर कॉम्पोनेंट के हिस्सों या कस्टम प्रॉपर्टी के बारे में जानने की ज़रूरत नहीं होती. साथ ही, होस्ट के अपने बॉक्स को हटाना आम तौर पर पैटर्न का मकसद होता है (कंपोज़िशन, पहले से मौजूद इनहेरिटेंस की कमी को पूरा करता है). दो असल चेतावनियां:all: inherit, UA की डिफ़ॉल्ट सेटिंग को मिटा देता है. इसलिए, खास प्रॉपर्टी के लिए स्कोप तय करें या डिफ़ॉल्ट सेटिंग वापस पाने के लिएrevertका इस्तेमाल करें. साथ ही, कॉन्क्रीट ब्लॉकर —getBoundingClientRect()औरgetClientRects(),display: contentsएलिमेंट के लिए शून्य दिखाते हैं. इसलिए, होस्ट के हिसाब से ऐंकर पोज़िशनिंग काम नहीं करती. अगर ये विकल्प आपके काम के नहीं हैं, तो::partया कस्टम प्रॉपर्टी का इस्तेमाल करें.
:state(): कॉम्पोनेंट की अपनी स्थितियों को स्टाइल करें
कस्टम एलिमेंट, this.#internals.states.add('busy') और .delete('busy') के ज़रिए ElementInternals का इस्तेमाल करके, इंटरनल बूलियन स्टेटस दिखा सकता है. लाइफ़साइकल के इस्तेमाल के लिए, कस्टम एलिमेंट देखें. ये स्टेटस, बाउंड्री के पार स्टाइलिंग चैनल बन जाते हैं — जैसे कि ::part और कस्टम प्रॉपर्टी. हालांकि, ये स्ट्रक्चर या वैल्यू के बजाय स्टेट के लिए होते हैं. :host(:state(name)) का इस्तेमाल करके, उन्हें शैडो ट्री में मैच करें. साथ ही, tag-name:state(name) का इस्तेमाल करके, उन्हें उपभोक्ता की स्टाइलशीट से मैच करें:
/* Inside the component's shadow tree. */
:host(:state(busy)) button { opacity: 0.6; pointer-events: none; }
/* From the consumer's stylesheet — a read-only public hook. */
favorite-button:state(favorited) { filter: drop-shadow(0 0 4px crimson); }
रिफ़्लेक्ट किए गए एट्रिब्यूट के उलट, कस्टम स्टेट बाहरी लोगों के लिए रीड-ओनली होती है: उपभोक्ता इसे स्टाइल कर सकते हैं, लेकिन इसे सेट या फ़ोर्ज नहीं कर सकते. इसलिए, कॉम्पोनेंट ही एकमात्र राइटर बना रहता है. जब भी कॉम्पोनेंट के पास स्टेट का मालिकाना हक हो और उसे सिर्फ़ स्टाइल करना हो, तो data-* एट्रिब्यूट के बजाय इसे प्राथमिकता दें.
@layer और कॉम्पोनेंट में मौजूद कंटेनर क्वेरी
- कैस्केड लेयर (
@layer) शैडो रूट के अंदर काम करती हैं और उसी के दायरे में होती हैं; शैडो ट्री में मौजूद लेयर का नाम, पेज में मौजूद उसी नाम की लेयर से अलग होता है. इनका इस्तेमाल करके, अपने कॉम्पोनेंट की स्टाइल (जैसे,@layer base, theme;) को क्रम से लगाएं. इससे, कस्टम प्रॉपर्टी और::partके ज़रिए उपभोक्ता के बदलावों को अब भी उम्मीद के मुताबिक लागू किया जा सकता है. - कंटेनर क्वेरी, रिस्पॉन्सिव कॉम्पोनेंट के लिए सही टूल हैं: कॉम्पोनेंट को व्यूपोर्ट के बजाय, उसे दी गई जगह के हिसाब से रिस्पॉन्स करना चाहिए. होस्ट या रैपर को कंटेनर के तौर पर तय करें. इसके लिए,
:hostकोdisplay: blockजैसा लेआउट बॉक्स दें, क्योंकि कस्टम एलिमेंट डिफ़ॉल्ट रूप सेdisplay: inlineपर सेट होते हैं और साइज़ कंटेनमेंट,inlineयाcontentsएलिमेंट पर लागू नहीं होता. इसके बाद, इसे क्वेरी करें, ताकि वही कॉम्पोनेंट साइडबार या पूरी चौड़ाई वाले हिस्से में अडजस्ट हो जाए.
:host {
display: block; /* Required: size containment does not apply to default display: inline */
container-type: inline-size;
}
@container (min-width: 30rem) {
.card { grid-template-columns: 1fr 2fr; }
}
फ़ॉलबैक रणनीतियां
::part, कैस्केड लेयर, और कंटेनर क्वेरी बड़े पैमाने पर उपलब्ध हैं. थीम मुख्य रूप से, इनहेरिट की गई कस्टम प्रॉपर्टी के ज़रिए उपलब्ध होती हैं. ये प्रॉपर्टी वहां भी काम करती हैं जहां ये सुविधाएं काम नहीं करतीं. जैसा कि ऊपर बताया गया है, :host-context() पर भरोसा न करें — यह सिर्फ़ Chromium के लिए है और आने वाले समय में इसका इस्तेमाल नहीं किया जा सकेगा.