Do czego służy pseudoklasa CSS „scope”?

Parametr :scope jest zdefiniowany w selektorach arkusza CSS 4 jako:

Pseudoklasa reprezentująca dowolny element w zestawie kontekstowych elementów referencyjnych. Jest to (potencjalnie pusty) zbiór elementów, np. określony przez querySelector(), lub element nadrzędny elementu <style scoped>, który służy do „określania zakresu” selektora tak, aby pasować tylko do drzewa podrzędnego.

Oto przykład użycia tej funkcji w <style scoped> (więcej informacji):

<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>

Powoduje to kolorowanie elementów li pierwszego zakresu (ul) na czerwono, a dzięki regule :scope umieszcza obramowanie wokół elementu ul. W kontekście tego elementu (<style scoped>) element ul pasuje do: :scope. To kontekst lokalny. Gdybyśmy dodali regułę :scope w zewnętrznym <style>, pasowałaby ona do całego dokumentu. Zasadniczo jest to odpowiednik :root.

Elementy kontekstowe

Prawdopodobnie znasz wersje Element systemu querySelector() i querySelectorAll(). Zamiast wysyłać zapytanie dotyczące całego dokumentu, możesz ograniczyć zbiór wyników do elementu kontekstowego:

<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>

Gdy zostaną one wywołane, przeglądarka zwraca typ NodeList z filtrem, który uwzględnia tylko zbiór węzłów, które a.) pasują do selektora oraz b., które są również potomnymi elementu kontekstu. W drugim przykładzie przeglądarka znajduje wszystkie elementy a, a potem odfiltrowuje te, których nie ma w elemencie scope. To działa, ale jeśli nie zachowasz ostrożności, może to prowadzić do dziwnych zachowań. Czytaj dalej.

Gdy selektor querySelector działa nieprawidłowo

W specyfikacji selektora jest naprawdę ważna kwestia, którą użytkownicy często przeoczają. Nawet po wywołaniu funkcji querySelector[All]() w elemencie selektory nadal dokonują oceny w kontekście całego dokumentu. Oznacza to, że mogą wystąpić nieprzewidziane sytuacje:

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

Super! W pierwszym przykładzie ul jest moim elementem, ale nadal mogę go używać i dopasowywać węzły. W drugim przypadku body nie jest nawet elementem potomnym mojego elementu, ale „body ul a” mimo to pasuje. Obie te kwestie są mylące i niezgodne z oczekiwaniami.

Warto tu dokonać porównania z biblioteką jQuery, która działa we właściwym podejściu i działa zgodnie z oczekiwaniami:

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

...wpisz :scope, aby rozwiązać te semantyczne łamigłówki.

Naprawianie metody querySelector za pomocą zakresu :scope

Obsługa WebKit niedawno umożliwia korzystanie z pseudoklasy :scope w: querySelector[All](). Możesz ją przetestować w Chrome Canary 27.

Pozwala on ograniczyć selektory do elementu kontekstu. Spójrzmy na przykład. W poniższym przykładzie parametr :scope służy do określania zakresu selektora na poddrzewo elementu zakresu. Tak, powiedziałem zakres 3 razy!

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

Używanie :scope sprawia, że semantyka metod querySelector() staje się bardziej przewidywalna i jest zgodna z działaniami innych osób, takich jak jQuery.

Wydajność jest lepsza?

Jeszcze nie :(

Ciekawi mnie, czy użycie narzędzia :scope w raporcie QS/QSA może zwiększyć wydajność. Więc... jako dobry inżynier przygotowałem test. Moje uzasadnienie: mniejsza przestrzeń dla przeglądarki do dopasowywania selektorów oznacza szybsze wyszukiwanie.

W moim eksperymencie WebKit trwa obecnie ok.1, 5–2 razy dłużej niż nieużywanie narzędzia :scope. Kurza twarz! Po naprawieniu strony crbug.com/222028 użycie jej teoretycznie powinno spowodować nieznaczne zwiększenie wydajności niż jej nieużywanie.