CSS :scope 의사 클래스는 어디에 사용되나요?

:scopeCSS 선택자 4에서 다음과 같이 정의됩니다.

문맥 참조 요소 집합에 있는 요소를 나타내는 의사 클래스입니다. 이는 명시적으로 지정된 요소 집합 (예: 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>

이렇게 하면 첫 번째 ulli 요소에 빨간색으로 색상이 지정되고 :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>

이러한 메서드가 호출되면 브라우저는 a.) 선택기와 일치하는 노드 집합 및 b.) 컨텍스트 요소의 하위 요소이기도 한 노드 집합만 포함하도록 필터링된 NodeList를 반환합니다. 따라서 두 번째 예에서 브라우저는 모든 a 요소를 찾은 다음 scope 요소에 없는 요소를 필터링합니다. 이것은 효과적이지만 주의하지 않으면 기묘한 동작이 발생할 수 있습니다. 읽어보세요.

querySelector 오류 발생 시

선택기 사양에서 사람들이 종종 간과하는 매우 중요한 사항이 있습니다. 요소에서 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 Canary 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를 사용하면 성능이 향상되는지 궁금했습니다. 그래서... 훌륭한 엔지니어처럼 테스트를 준비했습니다. 내 근거: 브라우저에서 선택기 매칭을 실행할 수 있는 영역이 작기 때문에 조회가 더 빨라집니다.

실험에서 WebKit은 현재 :scope를 사용하지 않는 것보다 최대 1.5~2배 더 오래 걸립니다. 이런! crbug.com/222028이 수정되면 사용하지 않는 것보다 이론적으로 성능이 약간 향상됩니다.