पब्लिश होने की तारीख: 8 अक्टूबर, 2024
सीएसएस नेस्टिंग से जुड़ी कुछ समस्याओं को ठीक करने के लिए, सीएसएस वर्किंग ग्रुप ने सीएसएस नेस्टिंग स्पेसिफ़िकेशन में CSSNestedDeclarations
इंटरफ़ेस जोड़ने का फ़ैसला लिया है. इस सुविधा के जुड़ने के बाद, स्टाइल के नियमों के बाद आने वाले एलान अब ऊपर नहीं शिफ़्ट होंगे. साथ ही, कुछ अन्य सुधार भी किए गए हैं.
ये बदलाव, Chrome के 130 वर्शन से उपलब्ध हैं. साथ ही, Firefox Nightly 132 और Safari टेक्नोलॉजी Preview 204 में किए जा सकते हैं.
ब्राउज़र सहायता
CSSNestedDeclarations
के बिना सीएसएस नेस्टिंग की समस्या
सीएसएस नेस्टिंग से जुड़ी समस्याओं में से एक यह है कि मूल रूप से, यह स्निपेट आपकी उम्मीद के मुताबिक काम नहीं करता:
.foo {
width: fit-content;
@media screen {
background-color: red;
}
background-color: green;
}
कोड को देखने पर, आपको लगता है कि <div class=foo>
एलिमेंट में green
background-color
है, क्योंकि background-color: green;
का एलान आखिरी बार आता है. हालांकि, Chrome के 130 से पहले के वर्शन में ऐसा नहीं होता. जिन वर्शन में CSSNestedDeclarations
काम नहीं करता उनमें एलिमेंट का background-color
red
होता है.
Chrome के 130 इस्तेमाल से पहले के असल नियम को पार्स करने के बाद, यह तरीका अपनाएं:
.foo {
width: fit-content;
background-color: green;
@media screen {
& {
background-color: red;
}
}
}
पार्स करने के बाद, सीएसएस में दो बदलाव हुए:
background-color: green;
को ऊपर की ओर शिफ़्ट करके, दो अन्य एलान के साथ जोड़ दिया गया.- नेस्ट किए गए
CSSMediaRule
को फिर से लिखा गया, ताकि&
सिलेक्टर का इस्तेमाल करके, उसके एलान को एक अतिरिक्तCSSStyleRule
में रैप किया जा सके.
आपको यहां एक और सामान्य बदलाव दिखेगा. इसमें पार्स करने वाला टूल, उन प्रॉपर्टी को खारिज कर देगा जिनमें यह काम नहीं करता.
"पार्स करने के बाद सीएसएस" की जांच करने के लिए, CSSStyleRule
पर मौजूद cssText
को फिर से पढ़ें.
इस इंटरैक्टिव प्लैटफ़ॉर्म पर जाकर, इसे खुद आज़माएं:
इस सीएसएस को फिर से क्यों लिखा गया है?
यह समझने के लिए कि यह इंटरनल रीराइट क्यों हुआ, आपको यह समझना होगा कि सीएसएस ऑब्जेक्ट मॉडल (सीएसएसओएम) में यह CSSStyleRule
कैसे दिखाया जाता है.
Chrome 130 से पहले के वर्शन में, पहले शेयर किया गया सीएसएस स्निपेट, इस तरह से क्रम में लगाया जाता है:
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.resolvedSelectorText = ".foo"
.specificity = "(0,1,0)"
.style (CSSStyleDeclaration, 2) =
- width: fit-content
- background-color: green
.cssRules (CSSRuleList, 1) =
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "&"
.resolvedSelectorText = ":is(.foo)"
.specificity = "(0,1,0)"
.style (CSSStyleDeclaration, 1) =
- background-color: red
CSSStyleRule
की सभी प्रॉपर्टी में से, इन दो प्रॉपर्टी का इस मामले में इस्तेमाल किया जा सकता है:
style
प्रॉपर्टी, जो एलान दिखाने वालाCSSStyleDeclaration
इंस्टेंस है.cssRules
प्रॉपर्टी, जो एकCSSRuleList
है. इसमें नेस्ट किए गए सभीCSSRule
ऑब्जेक्ट होते हैं.
सीएसएस स्निपेट के सभी एलान, CSStyleRule
की style
प्रॉपर्टी में खत्म हो जाते हैं. इस वजह से, जानकारी का नुकसान होता है. style
प्रॉपर्टी को देखते समय, यह पता नहीं चल पा रहा है कि background-color: green
को नेस्ट किए गए CSSMediaRule
के बाद बताया गया है.
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.style (CSSStyleDeclaration, 2) =
- width: fit-content
- background-color: green
.cssRules (CSSRuleList, 1) =
↳ …
यह एक समस्या है, क्योंकि सीएसएस इंजन के ठीक से काम करने के लिए यह ज़रूरी है कि वह किसी स्टाइल के नियम की शुरुआत में दिखने वाली प्रॉपर्टी से, दूसरे नियमों के साथ बीच में दिखने वाली प्रॉपर्टी के बीच अंतर कर सके.
CSSMediaRule
के अंदर मौजूद एलान, अचानक CSSStyleRule
में रैप हो रहे हैं: इसकी वजह यह है कि CSSMediaRule
को एलान शामिल करने के लिए डिज़ाइन नहीं किया गया था.
CSSMediaRule
में नेस्ट किए गए नियम हो सकते हैं. इन्हें cssRules
प्रॉपर्टी की मदद से ऐक्सेस किया जा सकता है. इसलिए, एलान अपने-आप CSSStyleRule
में रैप हो जाते हैं.
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "&"
.resolvedSelectorText = ":is(.foo)"
.specificity = "(0,1,0)"
.style (CSSStyleDeclaration, 1) =
- background-color: red
इस समस्या को कैसे हल करें?
सीएसएस वर्किंग ग्रुप ने इस समस्या को हल करने के लिए कई विकल्पों पर विचार किया.
सुझाए गए समाधानों में से एक यह था कि सभी बेर डिक्लेरेशन को नेस्ट किए गए CSSStyleRule
में रैप किया जाए. इसके लिए, नेस्टिंग सिलेक्टर (&
) का इस्तेमाल किया जाए. इस आइडिया को कई वजहों से खारिज कर दिया गया. इनमें &
को :is(…)
में बदलने के अनचाहे साइड इफ़ेक्ट भी शामिल हैं:
- इससे, सटीक जानकारी पर असर पड़ता है. ऐसा इसलिए होता है, क्योंकि
:is()
अपने सबसे खास आर्ग्युमेंट की खास जानकारी लेता है. - यह ओरिजनल आउटर सिलेक्टर में सूडो-एलिमेंट के साथ अच्छी तरह से काम नहीं करता. ऐसा इसलिए होता है, क्योंकि
:is()
अपनी सिलेक्टर सूची के आर्ग्युमेंट में, स्यूडो एलिमेंट को स्वीकार नहीं करता.
नीचे दिया गया उदाहरण देखें:
#foo, .foo, .foo::before {
width: fit-content;
background-color: red;
@media screen {
background-color: green;
}
}
पार्स करने के बाद, वह स्निपेट Chrome में 130 से पहले यह बन जाता है:
#foo,
.foo,
.foo::before {
width: fit-content;
background-color: red;
@media screen {
& {
background-color: green;
}
}
}
यह एक समस्या है, क्योंकि &
सिलेक्टर के साथ नेस्ट किया गया CSSRule
:
:is(#foo, .foo)
तक फ़्लैट कर देता है. साथ ही, सिलेक्टर की सूची से.foo::before
को हटा देता है.- इसमें
(1,0,0)
की खास बात यह है कि इसे बाद में ओवरराइट करना मुश्किल होता है.
इसकी जांच करने के लिए, देखें कि नियम किस तरह से क्रम में लगाता है:
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "#foo, .foo, .foo::before"
.resolvedSelectorText = "#foo, .foo, .foo::before"
.specificity = (1,0,0),(0,1,0),(0,1,1)
.style (CSSStyleDeclaration, 2) =
- width: fit-content
- background-color: red
.cssRules (CSSRuleList, 1) =
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = "&"
.resolvedSelectorText = ":is(#foo, .foo, .foo::before)"
.specificity = (1,0,0)
.style (CSSStyleDeclaration, 1) =
- background-color: green
देखने में इसका यह भी मतलब है कि .foo::before
का background-color
, green
के बजाय red
है.
सीएसएस वर्किंग ग्रुप ने एक और तरीका भी आज़माया. इसमें, नेस्ट किए गए सभी एलान को @nest
नियम में लपेटा गया. इस सुझाव को इसलिए खारिज कर दिया गया, क्योंकि इससे डेवलपर के अनुभव में गिरावट आएगी.
पेश है CSSNestedDeclarations
इंटरफ़ेस
नेस्ट किए गए डिक्लेरेशन नियम से जुड़ी जानकारी, सीएसएस वर्किंग ग्रुप के समाधान के तौर पर सेट की गई है.
नेस्ट किए गए एलान का यह नियम, Chrome 130 से Chrome में लागू किया गया है.
ब्राउज़र सहायता
नेस्ट किए गए एलान के नियम को लागू करने से, सीएसएस पार्सर में बदलाव होता है. इससे, सीधे तौर पर नेस्ट किए गए एलान, CSSNestedDeclarations
इंस्टेंस में अपने-आप रैप हो जाते हैं. सीरियलाइज़ होने पर, यह CSSNestedDeclarations
इंस्टेंस CSSStyleRule
की cssRules
प्रॉपर्टी में दिखता है.
उदाहरण के तौर पर, यहां दिया गया CSSStyleRule
देखें:
.foo {
width: fit-content;
@media screen {
background-color: red;
}
background-color: green;
}
Chrome 130 या उसके बाद के वर्शन में सीरियलाइज़ करने पर, यह ऐसा दिखता है:
↳ CSSStyleRule
.type = STYLE_RULE
.selectorText = ".foo"
.resolvedSelectorText = ".foo"
.specificity = (0,1,0)
.style (CSSStyleDeclaration, 1) =
- width: fit-content
.cssRules (CSSRuleList, 2) =
↳ CSSMediaRule
.type = MEDIA_RULE
.cssRules (CSSRuleList, 1) =
↳ CSSNestedDeclarations
.style (CSSStyleDeclaration, 1) =
- background-color: red
↳ CSSNestedDeclarations
.style (CSSStyleDeclaration, 1) =
- background-color: green
CSSNestedDeclarations
नियम CSSRuleList
में खत्म होता है, इसलिए पार्स करने वाला टूल background-color: green
एलान की जगह को बनाए रख सकता है: background-color: red
एलान (जो CSSMediaRule
का हिस्सा है) के बाद.
इसके अलावा, CSSNestedDeclarations
इंस्टेंस होने से, अब तक खारिज किए गए संभावित समाधानों की तरह कोई भी बुरा असर नहीं पड़ता: नेस्ट किए गए एलिमेंट का नियम, अपने पैरंट स्टाइल नियम के एलिमेंट और स्यूडो-एलिमेंट से पूरी तरह मेल खाता है. साथ ही, दोनों का व्यवहार एक जैसा होता है.
इस बात का सबूत है कि CSSStyleRule
के cssText
को वापस पढ़ लिया गया है. नेस्ट किए गए एलान के नियम की मदद से, यह इनपुट सीएसएस जैसी ही है:
.foo {
width: fit-content;
@media screen {
background-color: red;
}
background-color: green;
}
इसका आपके लिए क्या मतलब है
इसका मतलब है कि Chrome 130 के बाद से, सीएसएस नेस्टिंग काफ़ी बेहतर हो गई है. हालांकि, इसका यह भी मतलब है कि अगर आपने नेस्ट किए गए नियमों के साथ सादे एलान को इंटरवेल किया था, तो आपको अपने कुछ कोड की समीक्षा करनी पड़ सकती है.
नीचे दिया गया उदाहरण देखें, जिसमें @starting-style
का इस्तेमाल किया गया है
/* This does not work in Chrome 130 */
#mypopover:popover-open {
@starting-style {
opacity: 0;
scale: 0.5;
}
opacity: 1;
scale: 1;
}
Chrome 130 से पहले, ये एलान होस्ट कर दिए जाते थे. आखिर में, opacity: 1;
और scale: 1;
एलान CSSStyleRule.style
में जाकर, CSSStyleRule.cssRules
में CSSStartingStyleRule
(@starting-style
नियम को दिखाता है) के साथ दिखेंगे.
Chrome 130 से, एलान अब होस्ट नहीं किए जाते. साथ ही, आपको CSSStyleRule.cssRules
में दो नेस्ट किए गए CSSRule
ऑब्जेक्ट मिलते हैं. क्रम से: एक CSSStartingStyleRule
(@starting-style
नियम को दिखाता है) और एक CSSNestedDeclarations
जिसमें opacity: 1; scale: 1;
एलान शामिल हैं.
इस बदलाव की वजह से, @starting-style
एलान, CSSNestedDeclarations
इंस्टेंस में मौजूद एलान से ओवरराइट हो जाते हैं. इससे एंट्री ऐनिमेशन हट जाता है.
कोड को ठीक करने के लिए, पक्का करें कि @starting-style
ब्लॉक, सामान्य एलान के बाद आता हो. जैसे:
/* This works in Chrome 130 */
#mypopover:popover-open {
opacity: 1;
scale: 1;
@starting-style {
opacity: 0;
scale: 0.5;
}
}
अगर सीएसएस नेस्टिंग का इस्तेमाल करते समय, नेस्ट किए गए एलिमेंट को नेस्ट किए गए नियमों के ऊपर रखा जाता है, तो आपका कोड उन सभी ब्राउज़र के सभी वर्शन में ज़्यादातर ठीक से काम करता है जो सीएसएस नेस्टिंग के साथ काम करते हैं.
आखिर में, अगर आपको CSSNestedDeclarations
की उपलब्धता का पता लगाना है, तो यहां दिए गए JavaScript स्निपेट का इस्तेमाल करें:
if (!("CSSNestedDeclarations" in self && "style" in CSSNestedDeclarations.prototype)) {
// CSSNestedDeclarations is not available
}