Spec-Zone.ru › CSS

CSS-правило-ат-правило `@scope`

Базовая поддержка Недавно стало доступно

Эта функция работает в последних версиях устройств и браузеров. Она может не работать на старых устройствах и в старых версиях браузеров. Поддержка во всех браузерах доступна с марта 2026 года.

@scope CSS правило-ат-правило позволяет выбирать элементы в определённых поддеревьях DOM, точно задавая целевые элементы без написания чрезмерно специфичных селекторов, которые сложно переопределять, и без слишком тесной привязки селекторов к структуре DOM.

В JavaScript доступ к @scope можно получить через интерфейс объектной модели CSS CSSScopeRule.

Синтаксис

Правило-ат-правило @scope содержит один или несколько наборов правил (называемых ограниченными по области действия правилами стилей) и определяет область, в которой они применяются к выбранным элементам. @scope можно использовать двумя способами:

  1. Как отдельный блок внутри CSS. В этом случае он содержит вступительную часть с селекторами корня области и необязательного ограничителя области — они задают верхнюю и нижнюю границы области.

    @scope (scope root) to (scope limit) {
      /* … */
    }
    
  2. Как встроенные стили внутри элемента <style> в HTML. В этом случае вступительная часть опускается, а заключённый в нём набор правил автоматически ограничивается родительским элементом, содержащим элемент <style>.

    <parent-element>
      <style>
        @scope {
          /* rulesets */
        }
      </style>
    </parent-element>
    

    Также можно объединить встроенное @scope с селектором ограничителя области, как в @scope to (scope limit) { ... }.

Описание

Сложный веб-документ может включать такие компоненты, как заголовки, нижние колонтитулы, новостные статьи, карты, медиаплееры, рекламные объявления и другие. По мере роста сложности становится всё важнее эффективно управлять стилями этих компонентов, а грамотное ограничение области действия стилей помогает справиться с этой сложностью. Рассмотрим следующее дерево DOM:

body
└─ article.feature
   ├─ section.article-hero
   │  ├─ h2
   │  └─ img
   │
   ├─ section.article-body
   │  ├─ h3
   │  ├─ p
   │  ├─ img
   │  ├─ p
   │  └─ figure
   │     ├─ img
   │     └─ figcaption
   │
   └─ footer
      ├─ p
      └─ img

Чтобы выбрать элемент <img> внутри <section> с классом article-body, можно сделать следующее:

  • Написать селектор вида .feature > .article-body > img. Однако у него высокая специфичность, поэтому его сложно переопределить; кроме того, он жёстко привязан к структуре DOM. Если в будущем структура разметки изменится, возможно, придётся переписать CSS.
  • Написать менее специфичный селектор, например .article-body img. Однако он выберет все изображения внутри section.

В этом случае пригодится @scope. Оно позволяет определить точную область, внутри которой селекторы могут выбирать элементы. Например, решить описанную выше задачу можно с помощью отдельного блока @scope:

@scope (.article-body) to (figure) {
  img {
    border: 5px solid black;
    background-color: goldenrod;
  }
}

Селектор корня области .article-body определяет верхнюю границу области дерева DOM, в которой будет применяться набор правил, а селектор ограничителя области figure определяет нижнюю границу. В результате будут выбраны только элементы <img> внутри <section> с классом article-body, но не внутри элементов <figure>.

Примечание: Такое ограничение области — с верхней и нижней границами — обычно называют областью-пончиком.

Верхняя граница области включается в неё, а нижняя — нет. Чтобы изменить это поведение, можно объединить любой из селекторов с универсальным селектором дочернего элемента. Например, @scope (scope root) to (scope limit > *) сделает обе границы включительными, @scope (scope root > *) to (scope limit) сделает обе границы исключительными, а @scope (scope root > *) to (scope limit > *) задаст исключительную верхнюю и включительную нижнюю границу.

Чтобы выбрать все изображения внутри <section> с классом article-body, можно опустить ограничитель области:

@scope (.article-body) {
  img {
    border: 5px solid black;
    background-color: goldenrod;
  }
}

Можно также поместить блок @scope внутрь элемента <style>, который, в свою очередь, находится внутри <section> с классом article-body:

<section class="article-body">
  <style>
    @scope {
      img {
        border: 5px solid black;
        background-color: goldenrod;
      }
    }
  </style>

  <!-- ... -->
</section>

Примечание: Важно понимать, что, хотя @scope позволяет ограничить применение селекторов определёнными поддеревьями DOM, оно не изолирует стили полностью внутри этих поддеревьев. Особенно заметно это при наследовании: свойства, наследуемые дочерними элементами (например, color или font-family), будут по-прежнему наследоваться за пределами заданного ограничителя области.

Псевдокласс :scope внутри блоков @scope

В контексте блока @scope псевдокласс :scope позволяет удобно применять стили непосредственно к корню области:

@scope (.feature) {
  :scope {
    background: rebeccapurple;
    color: antiquewhite;
    font-family: sans-serif;
  }
}

При использовании :scope внутри блоков @scope следует учитывать следующее:

  • :scope добавляет специфичность уровня класса (подробности см. в разделе Специфичность в @scope).

  • В ограничителе области можно использовать :scope, чтобы задать требование к взаимному расположению ограничителя области и корня. Например:

    /* figure is only a limit when it is a direct child of the :scope */
    @scope (.article-body) to (:scope > figure) {
      /* … */
    }
    
  • Ограничитель области может ссылаться на элементы за пределами корня области с помощью :scope. Например:

    /* figure is only a limit when the :scope is inside .feature */
    @scope (.article-body) to (.feature :scope figure) {
      /* … */
    }
    
  • Ограниченные по области действия правила стилей не могут выходить за пределы поддерева. Такие выборки, как :scope + p, недопустимы, поскольку выбранный элемент находился бы за пределами поддерева.

  • Корень и ограничитель области можно задать как список селекторов; в этом случае будут определены несколько областей. В следующем примере стили применяются к любому <img> внутри <section> с классом article-hero или article-body, но не если оно вложено в <figure>:

    @scope (.article-hero, .article-body) to (figure) {
      img {
        border: 5px solid black;
        background-color: goldenrod;
      }
    }
    

Специфичность в @scope

Внутри правила @scope как простые селекторы, так и селектор вложенности & ведут себя так, как если бы перед ними был добавлен :where(:scope). Поскольку :where() имеет нулевую специфичность, простые селекторы и & не добавляют вес. Вес специфичности определяется остальной частью селектора. Например, специфичность селектора & img эквивалентна специфичности :where(:scope) img (0-0-1).

Предупреждение: Специфичность & внутри блоков @scope обрабатывается по-разному в зависимости от движка браузера и версии выпуска. Подробнее см. в разделе Совместимость с браузерами.

В обоих случаях в следующем блоке кода единственный вклад в специфичность вносит img:

@scope (.article-body) {
  /* img has a specificity of 0-0-1, as expected */
  img {
    /* … */
  }

  /* & img also has a specificity of 0-0-1 */
  & img {
    /* … */
  }
}

Напротив, явное использование :scope выбирает корень области и добавляет специфичность уровня класса (0-1-0), поскольку :scope — это псевдокласс. В следующем блоке кода специфичность :scope img равна 0-1-1:

@scope (.article-body) {
  /* :scope img has a specificity of 0-1-0 + 0-0-1 = 0-1-1 */
  :scope img {
    /* … */
  }
}

Разрешение конфликтов @scope

@scope добавляет новый критерий в каскад CSS: близость области действия. Согласно этому критерию, если стили двух областей конфликтуют, применяется стиль области, до корня которой от элемента по иерархии дерева DOM меньше переходов. Рассмотрим пример, чтобы понять, что это означает.

Возьмём следующий фрагмент HTML, где карточки с разными темами вложены друг в друга:

<div class="light-theme">
  <p>Light theme text</p>
  <div class="dark-theme">
    <p>Dark theme text</p>
    <div class="light-theme">
      <p>Light theme text</p>
    </div>
  </div>
</div>

Если написать CSS для тем следующим образом, возникнет проблема:

.light-theme {
  background: #cccccc;
}

.dark-theme {
  background: #333333;
}

.light-theme p {
  color: black;
}

.dark-theme p {
  color: white;
}

Предполагалось, что внутренний абзац будет чёрным, поскольку он находится внутри карточки со светлой темой. Однако на него нацелены и .light-theme p, и .dark-theme p. Поскольку правило .dark-theme p расположено позже в исходном коде, применяется именно оно, и абзац ошибочно становится белым.

Исправить это можно с помощью @scope:

@scope (.light-theme) {
  :scope {
    background: #cccccc;
  }
  p {
    color: black;
  }
}

@scope (.dark-theme) {
  :scope {
    background: #333333;
  }
  p {
    color: white;
  }
}

Теперь внутренний абзац правильно отображается чёрным. Это происходит потому, что от него до корня области .light-theme всего один уровень дерева DOM, а до корня области .dark-theme — два. Поэтому приоритет получает стиль светлой темы.

Примечание: Близость области действия важнее порядка в исходном коде, но сама уступает другим критериям с более высоким приоритетом, таким как важность, слои и специфичность.

Формальный синтаксис

Примеры

Базовые стили внутри корней областей

В этом примере мы используем два отдельных блока @scope, чтобы выбрать ссылки внутри элементов с классами .light-scheme и .dark-scheme соответственно. Обратите внимание, как :scope используется для выбора корней областей и применения к ним стилей. В этом примере корнями областей являются элементы <div>, которым назначены эти классы.

HTML

<div class="light-scheme">
  <p>
    MDN contains lots of information about
    <a href="/en-US/docs/Web/HTML">HTML</a>,
    <a href="/en-US/docs/Web/CSS">CSS</a>, and
    <a href="/en-US/docs/Web/JavaScript">JavaScript</a>.
  </p>
</div>

<div class="dark-scheme">
  <p>
    MDN contains lots of information about
    <a href="/en-US/docs/Web/HTML">HTML</a>,
    <a href="/en-US/docs/Web/CSS">CSS</a>, and
    <a href="/en-US/docs/Web/JavaScript">JavaScript</a>.
  </p>
</div>

CSS

div {
  padding: 10px;
}
@scope (.light-scheme) {
  :scope {
    background-color: plum;
  }

  a {
    color: darkmagenta;
  }
}

@scope (.dark-scheme) {
  :scope {
    background-color: darkmagenta;
    color: antiquewhite;
  }

  a {
    color: plum;
  }
}

Результат

Приведённый выше код отображается следующим образом:

Корни и ограничители областей

В этом примере фрагмент HTML соответствует структуре DOM, которую мы ранее рассмотрели в разделе Описание. Эта структура представляет собой типичное краткое содержание статьи. Обратите внимание на элементы <img>, вложенные на разных уровнях структуры.

Цель этого примера — показать, как с помощью корня и ограничителя области стилизовать элементы <img>, начиная с верхнего уровня иерархии, но только до элемента <img> внутри элемента <figure> (не включая его), фактически создав область-пончик.

HTML

<article class="feature">
  <section class="article-hero">
    <h2>Article heading</h2>
    <img alt="image" src="" />
  </section>

  <section class="article-body">
    <h3>Article subheading</h3>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam euismod
      consectetur leo, nec eleifend quam volutpat vitae. Duis quis felis at
      augue imperdiet aliquam. Morbi at felis et massa mattis lacinia. Cras
      pharetra velit nisi, ac efficitur magna luctus nec.
    </p>

    <img alt="image" src="" />

    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

    <figure>
      <img alt="image" src="" />
      <figcaption>My infographic</figcaption>
    </figure>
  </section>

  <footer>
    <p>Written by Chris Mills.</p>
    <img alt="image" src="" />
  </footer>
</article>

CSS

* {
  box-sizing: border-box;
}

article {
  margin-bottom: 20px;
  padding: 10px;
  border: 2px solid gray;
}

.article-hero,
.article-body,
article footer {
  padding: 20px;
  margin: 10px;
  border: 2px solid lightgray;
}

img {
  height: 100px;
  width: 100%;
  display: block;
  background-color: lightgray;
  color: black;
  padding: 10px;
}

В CSS у нас есть два блока @scope:

  • Первый блок @scope задаёт корнем области элементы с классом .feature (в данном случае только внешний <article>), демонстрируя, как @scope можно использовать для оформления определённой части HTML.
  • Второй блок @scope также задаёт корнем области элементы с классом .feature, но дополнительно определяет ограничитель области figure. Благодаря этому содержащиеся в нём наборы правил применяются только к подходящим элементам внутри корня области (в данном случае <article class="feature"> ... </article>), которые не вложены в дочерние элементы <figure>. Этот блок @scope содержит один набор правил, который задаёт для элементов <img> толстую чёрную рамку и золотистый цвет фона.
/* Scoped CSS */

@scope (.feature) {
  :scope {
    background: rebeccapurple;
    color: antiquewhite;
    font-family: sans-serif;
  }

  figure {
    background-color: white;
    border: 2px solid black;
    color: black;
    padding: 10px;
  }
}

/* Donut scope */

@scope (.feature) to (figure) {
  img {
    border: 5px solid black;
    background-color: goldenrod;
  }
}

Результат

В отображённом результате обратите внимание, что все элементы <img> оформлены толстой рамкой и золотистым фоном, кроме элемента внутри <figure> (с подписью «Моя инфографика»).

Спецификации

Спецификация
Каскадирование и наследование CSS, уровень 6
# scoped-styles
Модуль вложенности CSS, уровень 1
# nesting-at-scope

Совместимость с браузерами

Настольные компьютеры Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome для Android Firefox для Android Opera для Android Safari для iOS Samsung Internet WebView для Android WebView для iOS
scope
118
118
146
104
26.4
26–26.4Правила CSS внутри @scope не применяются к элементам <input> и <textarea>.
17.4–26
118
146
79
26.4
26–26.4Правила CSS внутри @scope не применяются к элементам <input> и <textarea>.
17.4–26
25.0
118
26.4
26–26.4Правила CSS внутри @scope не применяются к элементам <input> и <textarea>.
17.4–26
at-scope
143
143
142
127
26.2
143
142
94
26.2
30.0
143
26.2

См. также

  • :scope
  • CSSScopeRule
  • Специфичность
  • Определение селектора & в правиле @scope на css.oddbird.net (2025)
  • Ограничение области действия селекторов с помощью правила-ат-правила CSS @scope на developer.chrome.com (2023)

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@scope

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API