W3docs

CSS псевдокласс :scope

CSS псевдокласс :scope представляет элементы области видимости. Читайте о псевдоклассе и практикуйтесь с примерами.

CSS псевдокласс :scope соответствует элементу, относительно которого разрешается селектор — его опорному элементу. В обычных DOM-запросах опорным элементом является тот элемент, на котором вызывается метод запроса; внутри Shadow DOM — это корень теневого дерева.

На этой странице объясняется, что означает «область видимости» для селектора, почему :scope является преимущественно инструментом JavaScript, а не таблиц стилей, два основных места, где он меняет поведение, и подводные камни, которых стоит остерегаться.

Что такое опорный элемент

Каждый селектор сопоставляется относительно некоего элемента. Когда вы пишете CSS в таблице стилей, опорным элементом является корень документа, поэтому :scope там эквивалентен :root и сам по себе редко полезен.

:scope становится значимым, когда опорный элемент — не корень, что особенно важно при запросах к DOM из JavaScript:

  • element.querySelector(selector) и element.querySelectorAll(selector) разрешают селектор относительно element. Здесь :scope указывает на сам element.
  • Методы запросов у ShadowRoot используют корень теневого дерева как опорный элемент.

Без :scope селектор, переданный в element.querySelector(), по-прежнему сопоставляется с целым поддеревом, а не привязывается к element. Это удивляет многих разработчиков — см. подводный камень ниже.

Зачем использовать

Основная причина обращаться к :scope — привязать селектор к элементу, по которому выполняется запрос, чтобы можно было выбирать непосредственных потомков или иным образом выразить «относительно этого места»:

// Match only sections that are direct children of container.
container.querySelectorAll(':scope > section');

:scope значим внутри перечисленных выше методов запросов (querySelector, querySelectorAll и живой проверки Element.matches()). Он не оказывает особого эффекта в closest() или в обычных правилах таблиц стилей.

Примечание: старый атрибут <style scoped>, который когда-то позволял блоку <style> применяться только внутри родительского элемента, был удалён из браузеров. Сегодня изоляция стилей реализуется с помощью Shadow DOM (или инструментов сборки), а :scope остаётся помощником для DOM-запросов.

Версия

Selectors Level 4

Синтаксис

В таблице стилей синтаксис такой же, как у любого другого псевдокласса:

:scope {
  /* declarations — equivalent to :root in a normal stylesheet */
}

В JavaScript он передаётся внутри строки селектора:

element.querySelectorAll(':scope > .child');

Пример: привязка запроса к элементу

В примере ниже container.querySelector(':scope > section') выбирает только тот <section>, который является непосредственным потомком .container. Найденный раздел перекрашивается для подтверждения того, что запрос сработал.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .container {
        margin: 40px auto;
        max-width: 700px;
        background-color: #eeeeee;
        padding: 20px;
        box-shadow: 0 0 4px rgba(0, 0, 0, 0.25);
      }
      section {
        padding: 30px;
      }
    </style>
  </head>
  <body>
    <h2>:scope selector example</h2>
    <div class="container">
      <section>
        <p>
          Inside the scope.
        </p>
      </section>
    </div>
    <script>
      const container = document.querySelector('.container');
      const scopeElement = container.querySelector(':scope > section');
      scopeElement.style.backgroundColor = '#1c87c9';
      scopeElement.style.color = '#fff';
    </script>
  </body>
</html>

Частая ошибка: выбор непосредственных потомков

Самая распространённая причина использовать :scope — выбор непосредственных потомков элемента, по которому выполняется запрос. Комбинатор вроде > .x не может стоять самостоятельно — element.querySelector('> .x') выбрасывает SyntaxError. Ему нужна левая часть, и :scope её предоставляет:

<ul id="list">
  <li>A</li>
  <li>
    <ul>
      <li>B (nested)</li>
    </ul>
  </li>
</ul>
const list = document.getElementById('list');

// SyntaxError — "> li" is not a complete selector:
// list.querySelectorAll('> li');

// Correct: only the direct <li> children of #list (A and the one wrapping the nested list),
// NOT "B (nested)".
list.querySelectorAll(':scope > li');

Без :scope вызов list.querySelectorAll('li') вернул бы и вложенный элемент B, поскольку простой селектор потомков охватывает всё поддерево. :scope > — это идиоматический способ сказать «непосредственные потомки элемента, по которому выполняется запрос».

Поддержка браузерами

:scope поддерживается во всех современных браузерах для методов DOM-запросов. В обычной таблице стилей он не оказывает никакого эффекта сверх поведения :root.

Связанные главы

  • CSS Selectors — полный справочник по селекторам.
  • CSS Selector — основы синтаксиса селекторов.

Практика

Практика
Что означает область видимости (scope) в CSS?
Что означает область видимости (scope) в CSS?
Was this page helpful?