«Donut Scope», «Proximity» и «DOM Blasters»
По горячим следам предыдущего поста про область видимости делаю продолжение. Речь пойдёт о директиве @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» позволяет ограничить область видимости «сверху» и «снизу». Так можно создавать «дыры» внутри элементов, в которых селекторы не будут действовать. Полезно для ограничения глобальных стилей в сбросах.
@scope (body) to (.content) {
a {
text-decoration: none;
}
}
Ссылка в меню без подчёркивания
...
...
Ссылка в тексте с подчёркиванием
...
«Proximity» — часть механизма каскада, которая вводит понятие близости элемента к области видимости. При прочих равных применяется тот селектор, который будет ближе к области видимости в DOM-дереве.
@scope (.light-theme) {
a {
color: blue;
}
}
@scope (.dark-theme) {
a {
color: lightblue;
}
}
Ссылка
Ссылка
С обычной вложенностью ссылка внутри light-theme будет светло-синей, потому что применяется последнее по порядку правило. Со @scope ссылка внутри light-theme будет синей, потому что это правило ближе к области видимости light-theme.
«DOM Blasters» — так Крис Койер назвал применение @scope внутри без указания селектора в скобках. Это режим, в котором ближайший родительский для элемент используется как область видимости.
Ссылка
Ссылка
@scope {
a {
color: red;
}
}
Ссылка внутри первого будет отображаться как обычно. Ссылка во втором будет красной. Потому что второй — ближайший родительский элемент для , и в этом используется @scope.
Крис в своём докладе предложил смелую идею: а что, если все стили компонентов писать таким образом, используя и @scope? Пока непонятны преимущества и недостатки такого подхода в реальных условиях, но это идея уровня «что, если».
Крис провёл замеры на 10000 карточек со стилями в отдельном файле и в для каждой карточки. По количеству памяти и времени отрисовки разницы не было. Увеличился размер HTML, но gzip хорошо справился.
Такой бенчмарк не отражает реальность. 10000 одинаковых карточек действительно хорошо сжимаются, а браузер может применять оптимизации. Нужно проверять на реальном проекте с разными стилями компонентов.
#css
По горячим следам предыдущего поста про область видимости делаю продолжение. Речь пойдёт о директиве @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» позволяет ограничить область видимости «сверху» и «снизу». Так можно создавать «дыры» внутри элементов, в которых селекторы не будут действовать. Полезно для ограничения глобальных стилей в сбросах.
@scope (body) to (.content) {
a {
text-decoration: none;
}
}
Ссылка в меню без подчёркивания
...
...
Ссылка в тексте с подчёркиванием
...
«Proximity» — часть механизма каскада, которая вводит понятие близости элемента к области видимости. При прочих равных применяется тот селектор, который будет ближе к области видимости в DOM-дереве.
@scope (.light-theme) {
a {
color: blue;
}
}
@scope (.dark-theme) {
a {
color: lightblue;
}
}
Ссылка
Ссылка
С обычной вложенностью ссылка внутри light-theme будет светло-синей, потому что применяется последнее по порядку правило. Со @scope ссылка внутри light-theme будет синей, потому что это правило ближе к области видимости light-theme.
«DOM Blasters» — так Крис Койер назвал применение @scope внутри без указания селектора в скобках. Это режим, в котором ближайший родительский для элемент используется как область видимости.
Ссылка
Ссылка
@scope {
a {
color: red;
}
}
Ссылка внутри первого будет отображаться как обычно. Ссылка во втором будет красной. Потому что второй — ближайший родительский элемент для , и в этом используется @scope.
Крис в своём докладе предложил смелую идею: а что, если все стили компонентов писать таким образом, используя и @scope? Пока непонятны преимущества и недостатки такого подхода в реальных условиях, но это идея уровня «что, если».
Крис провёл замеры на 10000 карточек со стилями в отдельном файле и в для каждой карточки. По количеству памяти и времени отрисовки разницы не было. Увеличился размер HTML, но gzip хорошо справился.
Такой бенчмарк не отражает реальность. 10000 одинаковых карточек действительно хорошо сжимаются, а браузер может применять оптимизации. Нужно проверять на реальном проекте с разными стилями компонентов.
#css