सीएसएस :scope pseudo-class क्या है?

एरिक बिडेलमैन

सीएसएस सिलेक्टर 4 में, :scope की जानकारी इस तरह दी गई है:

एक बदली हुई क्लास, जो कॉन्टेक्स्चुअल रेफ़रंस एलिमेंट सेट में मौजूद किसी भी एलिमेंट को दिखाती है. यह एलिमेंट का एक (संभावित रूप से खाली) सेट है, जिसके बारे में साफ़ तौर पर बताया गया है, जैसे कि querySelector() या किसी <style scoped> एलिमेंट का पैरंट एलिमेंट. इसका इस्तेमाल सिलेक्टर को "स्कोप" करने के लिए किया जाता है, ताकि यह सिर्फ़ सबट्री के अंदर मैच हो सके.

इसे इस्तेमाल करने का एक उदाहरण <style scoped> में दिया गया है (ज़्यादा जानकारी):

<style>
    li {
    color: blue;
    }
</style>

<ul>
    <style scoped>
    li {
        color: red;
    }
    :scope {
        border: 1px solid red;
    }
    </style>
    <li>abc</li>
    <li>def</li>
    <li>efg</li>
</ul>

<ul>
    <li>hij</li>
    <li>klm</li>
    <li>nop</li>
</ul>

यह li एलिमेंट को पहले ul के लाल रंग में दिखाता है. साथ ही, :scope नियम की वजह से, यह ul के चारों ओर एक बॉर्डर बना देता है. ऐसा इसलिए, क्योंकि इस <style scoped> के संदर्भ में, ul :scope से मेल खाता है. यह स्थानीय संदर्भ है. अगर हम आउटर <style> में :scope नियम जोड़ते हैं, तो यह पूरे दस्तावेज़ से मेल खाएगा. वास्तव में, :root के बराबर.

काम के एलिमेंट

ऐसा हो सकता है कि आपको querySelector() और querySelectorAll() के Element वर्शन के बारे में जानकारी हो. पूरे दस्तावेज़ की क्वेरी करने के बजाय, नतीजे सेट को कॉन्टेक्स्चुअल एलिमेंट तक सीमित किया जा सकता है:

<ul>
    <li id="scope"><a>abc</a></li>
    <li>def</li>
    <li><a>efg</a></li>
</ul>
<script>
    document.querySelectorAll('ul a').length; // 2

    var scope = document.querySelector('#scope');
    scope.querySelectorAll('a').length; // 1
</script>

इन्हें कॉल किए जाने पर, ब्राउज़र ऐसा NodeList दिखाता है जिसे सिर्फ़ नोड के सेट को शामिल करने के लिए फ़िल्टर किया गया है. a.) सिलेक्टर से मैच करता है और b.) जो कॉन्टेक्स्ट एलिमेंट के डिसेंडेंट भी हैं. इसलिए, दूसरे उदाहरण में बताया गया है कि ब्राउज़र सभी a एलिमेंट को ढूंढता है, फिर उन एलिमेंट को फ़िल्टर कर देता है जो scope एलिमेंट में नहीं हैं. यह तरीका काम करता है. हालांकि, अगर आप सावधानी न बरतें, तो इसकी वजह से कुछ अजीब व्यवहार हो सकता है. आगे पढ़ें.

क्वेरीसिलेक्टर के गलत होने पर

चुनने वाले लोगों के बारे में दी गई खास जानकारी में एक ऐसी अहम बात है जिसे लोग अक्सर नज़रअंदाज़ कर देते हैं. भले ही, किसी एलिमेंट पर querySelector[All]() शुरू किया गया हो, पर सिलेक्टर, पूरे दस्तावेज़ के हिसाब से आकलन करते हैं. इसका मतलब है कि अनचाहे नतीजे हो सकते हैं:

    scope.querySelectorAll('ul a').length); // 1
    scope.querySelectorAll('body ul a').length); // 1

अरे वाह! पहले उदाहरण में, ul मेरा एलिमेंट है. फिर भी, मैं इसका इस्तेमाल कर पा रहा/रही हूं और नोड से मेल खा सकता/सकती हूं. दूसरी स्थिति में, body मेरे एलिमेंट का डिसेंडेंट भी नहीं है, लेकिन "body ul a" अब भी मेल खाता है. ये दोनों भ्रम की स्थिति पैदा करने वाले हैं और आपकी उम्मीद के मुताबिक नहीं हैं.

यहां jQuery से तुलना करना फ़ायदेमंद है, जो सही तरीका अपनाता है और आपकी उम्मीद के मुताबिक काम करता है:

    $(scope).find('ul a').length // 0
    $(scope).find('body ul a').length // 0

...अचानक से जुड़ी इन बातों को सुलझाने के लिए, :scope डालें.

:scope की मदद से querySelector को ठीक किया जा रहा है

WebKit को हाल ही में, querySelector[All]() में :scope स्यूडो-क्लास का इस्तेमाल करने की सुविधा मिल गई है. इसे Chrome कैनरी 27 में टेस्ट किया जा सकता है.

इसका इस्तेमाल करके, सिलेक्टर को कॉन्टेक्स्ट एलिमेंट तक सीमित करें का इस्तेमाल किया जा सकता है. आइए, एक उदाहरण देखते हैं. यहां दिए गए उदाहरण में, :scope का इस्तेमाल, स्कोप एलिमेंट के सबट्री के लिए सिलेक्टर को "स्कोप" करने के लिए किया गया है. बिलकुल सही, मैंने स्कोप तीन बार कहा!

    scope.querySelectorAll(':scope ul a').length); // 0
    scope.querySelectorAll(':scope body ul a').length); // 0
    scope.querySelectorAll(':scope a').length); // 1

:scope का इस्तेमाल करने से, querySelector() तरीकों के सिमेंटिक्स थोड़ा ज़्यादा अनुमान लगाने लायक हो जाते हैं. साथ ही, jQuery जैसे दूसरे लोग पहले से ही कर रहे होते हैं, उसके मतलब के हिसाब से सही हो जाते हैं.

परफ़ॉर्मेंस सबसे अच्छी रही?

अभी तक नहीं :(

मुझे जानना था कि क्या qS/qSA में :scope का इस्तेमाल करने से परफ़ॉर्मेंस बेहतर होती है. इसलिए... एक अच्छे इंजीनियर की तरह मैंने एक टेस्ट किया. मेरी वजह: सिलेक्टर मैचिंग के लिए ब्राउज़र की स्क्रीन कम होने का मतलब है कि तेज़ी से खोजने की सुविधा.

मेरे प्रयोग में, :scope का इस्तेमाल न करने की तुलना में WebKit को फ़िलहाल ~1.5-2 गुना ज़्यादा समय लगता है. ड्रेट! जब crbug.com/222028 समस्या ठीक हो जाती है, तो इसका इस्तेमाल न करने पर, इससे आपकी परफ़ॉर्मेंस बेहतर हो सकती है.