Кратко
СкопированоДиректива @scope ограничивает область действия CSS-правил внутри части DOM-дерева. Стили применяются только к элементам внутри заданного контейнера, но не применяются к элементам, попадающим в исключаемую часть (to) и их потомкам.
Пример
СкопированоЗаголовок внутри .article окрашивается в синий, заголовок-подпись внутри .media — нет (.media задана как граница to), заголовок в .aside тоже не затронут, он вне корня @scope:
<section class="article"> <h2 class="title">Заголовок статьи</h2> <figure class="media"> <img src="cat.jpg" alt="Котик" /> <figcaption class="title">Подпись к изображению</figcaption> </figure> <p>Текст…</p></section><section class="aside"> <h2 class="title">Боковая колонка</h2> <p>Текст…</p></section>
<section class="article">
<h2 class="title">Заголовок статьи</h2>
<figure class="media">
<img src="cat.jpg" alt="Котик" />
<figcaption class="title">Подпись к изображению</figcaption>
</figure>
<p>Текст…</p>
</section>
<section class="aside">
<h2 class="title">Боковая колонка</h2>
<p>Текст…</p>
</section>
@scope (.article) to (.media) { .title { color: #2E9AFF; }}
@scope (.article) to (.media) {
.title {
color: #2E9AFF;
}
}
Как пишется
СкопированоЯвные корень и граница
СкопированоКорень и граница задаются в скобках после @scope:
/* Граница необязательна */@scope (.component) { /* стили применяются ко всем потомкам .component */}/* С границей */@scope (<корень>) to (<граница>) { /* стили */}
/* Граница необязательна */
@scope (.component) {
/* стили применяются ко всем потомкам .component */
}
/* С границей */
@scope (<корень>) to (<граница>) {
/* стили */
}
Корень — один или несколько селекторов, от которых начинается область. Через запятую можно указать сразу несколько, для каждого создаётся своя отдельная область:
@scope (.article, .news, .post) { h2 { color: tomato; }}
@scope (.article, .news, .post) {
h2 {
color: tomato;
}
}
Граница (to) — селекторы, которые вырезаются из области. Попавшие под них элементы и их потомки не получают стили из этой области.
В селекторе границы можно использовать :scope, чтобы сослаться на элементы вне корня области. Это позволяет задавать условные исключения:
/* figure становится границей области только если .article-body находится внутри .feature*/@scope (.article-body) to (.feature :scope figure) { img { border: 4px solid #2E9AFF; }}
/*
figure становится границей области
только если .article-body находится внутри .feature
*/
@scope (.article-body) to (.feature :scope figure) {
img {
border: 4px solid #2E9AFF;
}
}
<article class="feature"> <section class="article-body"> <img src="photo.jpg" alt="Фото" /> <figure> <img src="photo2.jpg" alt="Фото в фигуре" /> </figure> </section></article>
<article class="feature">
<section class="article-body">
<img src="photo.jpg" alt="Фото" />
<figure>
<img src="photo2.jpg" alt="Фото в фигуре" />
</figure>
</section>
</article>
Слева .article находится внутри .feature — figure становится границей, рамку получает только первое изображение. Справа .article стоит без .feature — граница не активируется, рамку получают оба.
Внутри @scope работает псевдокласс :scope — он ссылается на корневой элемент области:
@scope (.widget) { :scope { display: block; } :scope > .title { font-weight: 600; }}
@scope (.widget) {
:scope {
display: block;
}
:scope > .title {
font-weight: 600;
}
}
Встроенный <style>
Скопировано@scope { можно поместить в тег <style> прямо в разметке нужного контейнера. Корнём области автоматически становится ближайший предок, содержащий этот <style>:
<article class="card"> <style> @scope { .title { color: rebeccapurple; } } </style> <h3 class="title">Новость</h3> <p>Текст…</p> <footer class="card__footer">…</footer></article>
<article class="card">
<style>
@scope {
.title { color: rebeccapurple; }
}
</style>
<h3 class="title">Новость</h3>
<p>Текст…</p>
<footer class="card__footer">…</footer>
</article>
Специфичность и вложенные конструкции
Скопировано@scope не изменяет специфичность селекторов, они участвуют в каскаде как обычно:
.card .title { color: red;}@scope (.card) { .title { color: blue; }}
.card .title {
color: red;
}
@scope (.card) {
.title {
color: blue;
}
}
.card имеет более высокую специфичность, чем .title, заголовок останется красным.
Внутри @scope работают и другие CSS-конструкции. Например, @media:
@scope (.card) { @media (width > 700px) { .title { font-size: 2rem; } }}
@scope (.card) {
@media (width > 700px) {
.title {
font-size: 2rem;
}
}
}
Правило применяется только к .card, но дополнительно зависит от условия медиазапроса.
Как понять
Скопировано@scope — это способ ограничить CSS определённым блоком страницы. Например, карточкой или виджетом. Стили внутри такого блока не влияют на остальные части страницы и не требуют усложнения селекторов или переименования классов. Это помогает:
- изолировать стили отдельных блоков интерфейса (например, карточек, статей, виджетов);
- исключать части блока из области применения через
to, чтобы стили не затрагивали эти элементы и их потомков;( . . . ) - уменьшать конфликты CSS без повышения специфичности.
При этом важно понимать, что @scope не создаёт полной изоляции, как, например, Shadow DOM. Он ограничивает только применение селекторов, но не влияет на наследование CSS.
Например, если внутри области есть вложенный элемент, он может получить стили через наследование:
<section class="card"> <div class="inner"> Текст внутри вложенного элемента </div></section>
<section class="card">
<div class="inner">
Текст внутри вложенного элемента
</div>
</section>
@scope (.card) { .card { color: red; }}
@scope (.card) {
.card {
color: red;
}
}
В этом случае текст внутри .inner тоже станет красным, потому что color — это наследуемое свойство. @scope ограничил селектор, но не отменил механизм наследования CSS.
Подсказки
Скопировано💡 Избегайте слишком широких корней области (например, main), так как это увеличивает вероятность случайных пересечений стилей. Лучше использовать узкие контейнеры вроде .component, чтобы изолировать поведение блока.
💡 Для виджетов, внедряемых в сторонние страницы, вариант со встроенным <style> особенно удобен.
💡 Используйте :where для базовых (служебных) стилей, которые не должны увеличивать специфичность и легко переопределяются другими правилами, к примеру:
@scope (.card) { :where(.title) { margin: 0; }}
@scope (.card) {
:where(.title) {
margin: 0;
}
}
Здесь :where имеет нулевую специфичность, поэтому такие стили проще переопределять.
- Chrome 118, поддерживается
- Edge 118, поддерживается
- Firefox 146, поддерживается
- Safari 17.4, поддерживается