बीईएम। फ्रंट-एंड डेवलपमेंट की दुनिया में प्रतीत होने वाली सभी तकनीकों की तरह, बीईएम प्रारूप में सीएसएस लिखना ध्रुवीकरण हो सकता है। लेकिन यह है - कम से कम मेरे ट्विटर बबल में - बेहतर पसंद की जाने वाली सीएसएस पद्धतियों में से एक।
व्यक्तिगत रूप से, मुझे लगता है कि बीईएम अच्छा है, और मुझे लगता है कि आपको इसका इस्तेमाल करना चाहिए। लेकिन मैं यह भी समझता हूं कि आप शायद ऐसा क्यों न करें।
बीईएम पर आपकी राय के बावजूद, यह कई लाभ प्रदान करता है, सबसे बड़ा यह है कि यह सीएसएस कैस्केड में विशिष्टता के टकराव से बचने में मदद करता है। ऐसा इसलिए है, क्योंकि यदि ठीक से उपयोग किया जाता है, तो बीईएम प्रारूप में लिखे गए किसी भी चयनकर्ता के पास समान विशिष्टता स्कोर होना चाहिए (0,1,0
). मैंने वर्षों से (सरकार, विश्वविद्यालयों और बैंकों के बारे में सोचें) बड़े पैमाने पर वेबसाइटों के लिए CSS की रूपरेखा तैयार की है, और यह इन बड़ी परियोजनाओं पर है जहाँ मैंने पाया है कि BEM वास्तव में चमकता है। CSS लिखने में तब और मज़ा आता है जब आपको विश्वास हो कि आप जो शैली लिख रहे हैं या संपादित कर रहे हैं वह साइट के किसी अन्य भाग को प्रभावित नहीं कर रही है।
वास्तव में अपवाद हैं जहां विशिष्टता जोड़ने के लिए इसे पूरी तरह स्वीकार्य माना जाता है। उदाहरण के लिए: द :hover
और :focus
छद्म वर्ग। जिनका एक विशिष्टता स्कोर है 0,2,0
. दूसरा छद्म तत्व है - जैसे ::before
और ::after
- जिसका विशिष्टता स्कोर है 0,1,1
. हालांकि इस लेख के बाकी हिस्सों के लिए, मान लें कि हम कोई अन्य विशिष्टता रेंगना नहीं चाहते हैं। 🤓
लेकिन मैं वास्तव में यहां आपको बीईएम पर बेचने के लिए नहीं हूं। इसके बजाय, मैं इस बारे में बात करना चाहता हूं कि आधुनिक सीएसएस चयनकर्ताओं के साथ हम इसका उपयोग कैसे कर सकते हैं - सोचें :is()
, :has()
, :where()
, आदि - भी प्राप्त करने के लिए अधिक इसका नियंत्रण कास्केड.
आधुनिक CSS चयनकर्ताओं के बारे में यह क्या है?
RSI सीएसएस चयनकर्ता स्तर 4 युक्ति तत्वों का चयन करने के लिए हमें कुछ शक्तिशाली नए (आईएसएच) तरीके देता है। मेरे कुछ पसंदीदा में शामिल हैं :is()
, :where()
, तथा :not()
, जिनमें से प्रत्येक सभी आधुनिक ब्राउज़रों द्वारा समर्थित है और आजकल लगभग किसी भी प्रोजेक्ट पर उपयोग करने के लिए सुरक्षित है।
:is()
और :where()
मूल रूप से एक ही चीज हैं सिवाय इसके कि वे विशिष्टता को कैसे प्रभावित करते हैं। विशेष रूप से, :where()
का हमेशा एक विशिष्टता स्कोर होता है 0,0,0
. हाँ, यहाँ तक कि :where(button#widget.some-class)
कोई विशिष्टता नहीं है। इस बीच, की विशिष्टता :is()
उच्चतम विशिष्टता के साथ इसकी तर्क सूची में तत्व है। इसलिए, हमारे पास पहले से ही दो आधुनिक चयनकर्ताओं के बीच एक कैस्केड-विवादास्पद अंतर है जिसके साथ हम काम कर सकते हैं।
अविश्वसनीय रूप से शक्तिशाली :has()
संबंधपरक छद्म वर्ग भी है तेजी से ब्राउज़र समर्थन प्राप्त करना (और तब से CSS की सबसे बड़ी नई विशेषता है ग्रिड, मेरी विनम्र राय में)। हालाँकि, लेखन के समय, ब्राउज़र के लिए समर्थन :has()
अभी उत्पादन में उपयोग के लिए काफी अच्छा नहीं है।
लेमे ने मेरे बीईएम में उन छद्म वर्गों में से एक को चिपका दिया और ...
/* ❌ specificity score: 0,2,0 */
.something:not(.something--special) {
/* styles for all somethings, except for the special somethings */
}
वूप्स! वह विशिष्टता स्कोर देखें? याद रखें, बीईएम के साथ हम आदर्श रूप से चाहते हैं कि हमारे चयनकर्ताओं के पास विशिष्टता स्कोर हो 0,1,0
। क्यों है 0,2,0
बुरा? इसी उदाहरण पर विचार करें, विस्तारित:
.something:not(.something--special) {
color: red;
}
.something--special {
color: blue;
}
भले ही दूसरा चयनकर्ता स्रोत क्रम में अंतिम हो, पहले चयनकर्ता की उच्च विशिष्टता (0,2,0
) जीतता है, और का रंग .something--special
तत्वों पर सेट किया जाएगा red
. यही है, यह मानते हुए कि आपका बीईएम ठीक से लिखा गया है और चयनित तत्व में दोनों हैं .something
बेस क्लास और .something--special
संशोधक वर्ग ने इसे HTML में लागू किया।
लापरवाही से उपयोग किए जाने पर, ये छद्म वर्ग कैस्केड को अप्रत्याशित तरीके से प्रभावित कर सकते हैं। और यह इस प्रकार की विसंगतियां हैं जो आगे चलकर सिरदर्द पैदा कर सकती हैं, विशेष रूप से बड़े और अधिक जटिल कोडबेस पर।
डांग। तो अब क्या?
याद रखें कि मैं किस बारे में कह रहा था :where()
और तथ्य यह है कि इसकी विशिष्टता शून्य है? हम इसका उपयोग अपने लाभ के लिए कर सकते हैं:
/* ✅ specificity score: 0,1,0 */
.something:where(:not(.something--special)) {
/* etc. */
}
इस चयनकर्ता का पहला भाग (.something
) का सामान्य विशिष्टता स्कोर प्राप्त करता है 0,1,0
. लेकिन :where()
- और इसके अंदर की हर चीज - की एक विशिष्टता है 0
, जो चयनकर्ता की विशिष्टता को और अधिक नहीं बढ़ाता है।
:where()
हमें घोंसला बनाने की अनुमति देता है
जो लोग विशिष्टता के बारे में मेरे जितना परवाह नहीं करते हैं (और यह शायद बहुत से लोग हैं, निष्पक्ष होने के लिए) नेस्टिंग की बात आती है तो यह बहुत अच्छा होता है। कुछ निश्चिंत कीबोर्ड स्ट्रोक के साथ, हम इस तरह CSS के साथ समाप्त हो सकते हैं (ध्यान दें कि मैं संक्षिप्तता के लिए Sass का उपयोग कर रहा हूं):
.card { ... }
.card--featured {
/* etc. */
.card__title { ... }
.card__title { ... }
}
.card__title { ... }
.card__img { ... }
इस उदाहरण में, हमारे पास ए .card
अवयव। जब यह एक "फीचर्ड" कार्ड होता है ( .card--featured
क्लास), कार्ड के शीर्षक और छवि को अलग तरह से स्टाइल करने की आवश्यकता है। लेकिन, जैसा कि हम अभी पता है, उपरोक्त कोड एक विशिष्टता स्कोर में परिणाम देता है जो हमारे सिस्टम के बाकी हिस्सों के साथ असंगत है।
इसके बजाय एक कठोर विशिष्टता वाले बेवकूफ ने ऐसा किया हो सकता है:
.card { ... }
.card--featured { ... }
.card__title { ... }
.card__title--featured { ... }
.card__img { ... }
.card__img--featured { ... }
यह इतना बुरा नहीं है, है ना? सच कहूँ तो, यह सुंदर सीएसएस है।
हालांकि एचटीएमएल में एक नकारात्मक पहलू है। अनुभवी बीईएम लेखक शायद क्लंकी टेम्प्लेट लॉजिक के बारे में दर्द से अवगत हैं जो कई तत्वों के लिए सशर्त रूप से संशोधक वर्गों को लागू करने के लिए आवश्यक है। इस उदाहरण में, HTML टेम्पलेट को सशर्त रूप से जोड़ने की आवश्यकता है --featured
तीन तत्वों के लिए संशोधक वर्ग (.card
, .card__title
, तथा .card__img
) हालांकि वास्तविक दुनिया के उदाहरण में शायद और भी अधिक। वह बहुत कुछ है if
बयान।
RSI :where()
चयनकर्ता हमें बहुत कम टेम्प्लेट लॉजिक लिखने में मदद कर सकता है - और बूट करने के लिए कम बीईएम कक्षाएं - विशिष्टता के स्तर को जोड़े बिना।
.card { ... }
.card--featured { ... }
.card__title { ... }
:where(.card--featured) .card__title { ... }
.card__img { ... }
:where(.card--featured) .card__img { ... }
यहाँ एक ही बात है लेकिन सास में (अनुगामी ध्यान दें ऐम्परसेंड):
.card { ... }
.card--featured { ... }
.card__title {
/* etc. */
:where(.card--featured) & { ... }
}
.card__img {
/* etc. */
:where(.card--featured) & { ... }
}
विभिन्न बाल तत्वों के लिए संशोधक कक्षाओं को लागू करने पर आपको इस दृष्टिकोण का चयन करना चाहिए या नहीं, यह व्यक्तिगत प्राथमिकता का विषय है। लेकिन कम से कम :where()
हमें अब विकल्प देता है!
गैर-बीईएम एचटीएमएल के बारे में क्या?
हम एक आदर्श दुनिया में नहीं रहते हैं। कभी-कभी आपको HTML से निपटने की ज़रूरत होती है जो आपके नियंत्रण से बाहर है। उदाहरण के लिए, एक तृतीय-पक्ष स्क्रिप्ट जो HTML को इंजेक्ट करती है जिसे आपको स्टाइल करने की आवश्यकता होती है। वह मार्कअप अक्सर BEM वर्ग नामों के साथ नहीं लिखा जाता है। कुछ मामलों में वे शैलियाँ आईडी के अलावा कक्षाओं का उपयोग नहीं करती हैं!
एक बार फिर, :where()
हमारी पीठ है। यह समाधान थोड़ा हैक करने वाला है, क्योंकि हमें किसी तत्व के वर्ग को संदर्भित करने की आवश्यकता है जो कि डोम ट्री के आगे कहीं मौजूद है जिसे हम जानते हैं।
/* ❌ specificity score: 1,0,0 */
#widget {
/* etc. */
}
/* ✅ specificity score: 0,1,0 */
.page-wrapper :where(#widget) {
/* etc. */
}
हालांकि मूल तत्व को संदर्भित करना थोड़ा जोखिम भरा और प्रतिबंधात्मक लगता है। क्या होगा यदि वह मूल वर्ग बदलता है या किसी कारण से नहीं है? एक बेहतर (लेकिन शायद समान रूप से हैकी) समाधान का उपयोग करना होगा :is()
बजाय। याद रखें, की विशिष्टता :is()
इसकी चयनकर्ता सूची में सबसे विशिष्ट चयनकर्ता के बराबर है।
इसलिए, एक वर्ग को संदर्भित करने के बजाय हम जानते हैं (या आशा!) मौजूद है :where()
, जैसा कि ऊपर दिए गए उदाहरण में है, हम एक बने-बनाए वर्ग और को संदर्भित कर सकते हैं टैग।
/* ✅ specificity score: 0,1,0 */
:is(.dummy-class, body) :where(#widget) {
/* etc. */
}
कभी मौजूद body
हमें हमारा चयन करने में मदद करेगा #widget
तत्व, और की उपस्थिति .dummy-class
उसी के अंदर वर्ग :is()
देता है body
चयनकर्ता एक वर्ग के रूप में एक ही विशिष्टता स्कोर (0,1,0
)… और का उपयोग :where()
सुनिश्चित करता है कि चयनकर्ता को इससे अधिक विशिष्ट नहीं मिलता है।
बस!
इसी तरह हम की आधुनिक विशिष्टता-प्रबंधन सुविधाओं का लाभ उठा सकते हैं :is()
और :where()
बीईएम प्रारूप में सीएसएस लिखते समय हमें मिलने वाली विशिष्टता टकराव की रोकथाम के साथ-साथ छद्म-वर्ग। और बहुत दूर के भविष्य में नहीं, एक बार :has()
फ़ायरफ़ॉक्स समर्थन प्राप्त करें (यह वर्तमान में लेखन के समय एक ध्वज के पीछे समर्थित है) हम इसकी विशिष्टता को पूर्ववत करने के लिए इसे :where() के साथ जोड़ना चाहेंगे।
चाहे आप बीईएम के नामकरण पर पूरी तरह से जाएं या नहीं, मुझे उम्मीद है कि हम इस बात से सहमत हो सकते हैं कि चयनकर्ता विशिष्टता में निरंतरता होना अच्छी बात है!