По горячим следам предыдущего поста про область видимости делаю продолжение. Речь пойдёт о директиве
@scope в целом и подходах «Donut Scope», «Proximity» и «DOM Blasters» (названы так в докладе Криса Койера) в частности.@scope — новая директива CSS, доступная на данный момент во всех актуальных версиях основных браузеров (получила статус Baseline Newly Available в декабре 2025). Директива предназначена для управления областью видимости.В базовом виде
@scope создаёт область видимости, за пределы которой селекторы не действуют. Можно писать более простые селекторы и использовать селекторы типа без риска что-то задеть:@scope (.card) {
:scope {
...
}
.title {
...
}
button {
...
}
}Стили
.title и button применятся внутри .card и не повлияют на элементы вне .card. Селектор :scope позволяет стилизовать корневой элемент области видимости, в данном случае .card. В таком виде это не особо полезно и возможно без @scope:/* Вложенность даёт тот же эффект */
.card {
...
.title {
...
}
button {
...
}
}
«Donut Scope» позволяет ограничить область видимости «сверху» и «снизу». Так можно создавать «дыры» внутри элементов, в которых селекторы не будут действовать. Полезно для ограничения глобальных стилей в сбросах.
<style>
@scope (body) to (.content) {
a {
text-decoration: none;
}
}
</style>
<nav>
<a href="...">
Ссылка в меню без подчёркивания
</a>
...
<nav>
<div class="content">
...
<a href="...">
Ссылка в тексте с подчёркиванием
</a>
...
</div>
«Proximity» — часть механизма каскада, которая вводит понятие близости элемента к области видимости. При прочих равных применяется тот селектор, который будет ближе к области видимости в DOM-дереве.
<style>
@scope (.light-theme) {
a {
color: blue;
}
}
@scope (.dark-theme) {
a {
color: lightblue;
}
}
</style>
<div class="dark-theme">
<a href="...">Ссылка</a>
<div class="light-theme">
<a href="...">Ссылка</a>
</div>
</div>
С обычной вложенностью ссылка внутри
light-theme будет светло-синей, потому что применяется последнее по порядку правило. Со @scope ссылка внутри light-theme будет синей, потому что это правило ближе к области видимости light-theme.«DOM Blasters» — так Крис Койер назвал применение
@scope внутри <style> без указания селектора в скобках. Это режим, в котором ближайший родительский для <style> элемент используется как область видимости.<div>
<a href="...">Ссылка</a>
</div>
<div>
<a href="...">Ссылка</a>
<style>
@scope {
a {
color: red;
}
}
</style>
</div>
Ссылка внутри первого
<div> будет отображаться как обычно. Ссылка во втором <div> будет красной. Потому что второй <div> — ближайший родительский элемент для <style>, и в этом <style> используется @scope.Крис в своём докладе предложил смелую идею: а что, если все стили компонентов писать таким образом, используя
<style> и @scope? Пока непонятны преимущества и недостатки такого подхода в реальных условиях, но это идея уровня «что, если».Крис провёл замеры на 10000 карточек со стилями в отдельном файле и в
<style> для каждой карточки. По количеству памяти и времени отрисовки разницы не было. Увеличился размер HTML, но gzip хорошо справился.Такой бенчмарк не отражает реальность. 10000 одинаковых карточек действительно хорошо сжимаются, а браузер может применять оптимизации. Нужно проверять на реальном проекте с разными стилями компонентов.
#css