@scope (.card) {
.title { /* ... */ }
.image { /* ... */ }
.link { /* ... */ }
}В CSS всегда была проблема с изоляцией стилей, особенно на больших проектах. Её решают по-разному: префиксы, конвенции по именованию классов (БЭМ), CSS-modules, scoped styles (Vue) и т.д. Все это - попытки решить проблему. На самом деле решение есть - Shadow DOM, который обеспечивает изоляцию разметки и стилей в отдельном поддереве DOM. Причём Shadow DOM это не эксклюзивная возможность веб-компонентов. Её можно использовать и для обычных элементов. Однако в таком виде не прижилось. Нужен более простой механизм для создания областей видимости, который был бы доступен в CSS. Этим механизмом в скором времени станет директива
@scope. Поддержка этой директивы будет добавлена в Chrome 117. Safari и Firefox идею поддержали и обсуждают детали реализации.Директива
@scope позволяет задать селектор элемента, который будет создавать область видимости. Внутри @scope можно указывать стили, которые будут применяться только в этой области видимости. В примере стили применятся только к тем img, которые находятся внутри .media-block:<style>
@scope (.media-block) {
img {
border-radius: 50%;
}
}
</style>
<div class="media-block">
<!-- стили применяются -->
<img src="..." alt="...">
</div>
<!-- стили не применяются -->
<img src="..." alt="...">
Если
@scope указан в HTML и при этом не указан селектор, то ближайший родитель элемента <style> будет использоваться как корень для создания области видимости:<div> <!-- корень области видимости -->
<style>
@scope {
p {
color: red;
}
}
</style>
<p>Красный</p>
</div>
<p>Не красный</p>
Опционально можно указать второй селектор после ключевого слова
to. Это задаёт границу области видимости. Таким образом, можно задавать область видимости не на все дочерние узлы, а только на конкретную часть поддерева:<style>
@scope (.media-block) to (.content) {
img {
border-radius: 50%;
}
}
</style>
<div class="media-block">
<!-- стили применяются -->
<img src="..." alt="...">
<div class="content">
<!-- стили не применяются -->
<img src="..." alt="...">
</div>
</div>
Специальный псевдоселектор
:scope позволяет обращаться к корню области видимости и стилизовать сам корень или его дочерние элементы в зависимости от контекста:<style>
@scope (.media-block) {
:scope { /* .media-block */ }
:scope img { /* .media-block img */ }
aside:scope { /* aside.media-block */ }
}
</style>
<div class="media-block">
<img src="..." alt="...">
</div>
Эта штука вполне может вытеснить БЭМ и различные библиотеки, когда появится полноценная поддержка. Ждём. А пока подробнее про @scope с примерами и нюансами можно почитать в черновике спецификации.
PS. Поддержка
@scope была добавлена в Chrome 117 за флагом, а в 118 включили полную поддержку для всех. Также поддержку добавили в Safari TP 185