Вложенность CSS

Источник: «CSS Nesting»
Одна из наших любимых функций CSS препроцессора теперь встроена в CSS: вложения правил стиля.

До появления вложенности каждый селектор нужно было объявлять отдельно друг от друга. Это приводит к повторению, большому объёму таблиц стилей и разрозненности процесса создания.

До:

.nesting {
color: hotpink;
}

.nesting > .is {
color: rebeccapurple;
}

.nesting > .is > .awesome {
color: deeppink;
}

После появления вложенности селекторы могут быть продолжены, а связанные с ними правила стиля могут быть сгруппированы внутри.

.nesting {
color: hotpink;

> .is {
color: rebeccapurple;

> .awesome {
color: deeppink;
}
}
}

See the Pen

Вложенность помогает разработчикам, уменьшая необходимость повторения селекторов, а также совместно размещая правила стиля для связанных элементов. Это также может помочь стилям соответствовать HTML, на который они нацелены. Если компонент .nesting в предыдущем примере был удалён из проекта, вы можете удалить всю группу вместо поиска в файлах связанных экземпляров селекторов.

Вложенность может помочь с:

Вложенность доступна в Chrome 112, а также в Safari Technical Preview 162.

Начало работы с Вложенностью CSS

На протяжении оставшейся части этой статьи используется следующая демо-песочница (к сожалению, в оригинальной статье не указана ссылка, только скриншот), которая поможет вам визуализировать выбор. В этом состоянии по умолчанию ничего не выбрано и всё видно. Выбирая различные формы и размеры, вы можете попрактиковаться в синтаксисе и увидеть его в действии.

Скриншот демо-песочницы css вложения

Внутри песочницы находятся круги, треугольники и квадраты. Некоторые из них маленькие, средние или большие. Одни синие, другие розовые или фиолетовые. Все они находятся внутри элемента .demo. Ниже приведён HTML код элементов, на который вы будете ориентироваться.

<div class="demo">
<div class="sm triangle pink"></div>
<div class="sm triangle blue"></div>
<div class="square blue"></div>
<div class="sm square pink"></div>
<div class="sm square blue"></div>
<div class="circle pink"></div>

</div>

Примеры вложения

Вложение CSS позволяет определять стили для элемента в контексте другого селектора.

.parent {
color: blue;

.child {
color: red;
}
}

В этом примере селектор класса .child вложен в селектор класса .parent. Это означает, что вложенный селектор .child будет применяться только к элементам, которые являются дочерними элементами элементов с классом .parent.

В качестве альтернативы этот пример можно было бы написать с использованием символа &, чтобы явно указать, где должен быть размещён родительский класс.

.parent {
color: blue;

& .child {
color: red;
}
}

Эти два примера функционально эквивалентны, и причина, по которой у вас есть варианты, станет яснее, когда в этой статье будут рассмотрены более сложные примеры.

Выделение кругов

Для первого примера задача состоит в том, чтобы добавить стили затухания и размытия только для кругов внутри .demo.

Без вложенности, CSS сегодня:

.demo .circle {
opacity: .25;
filter: blur(25px);
}

С вложенностью, есть два допустимых способа:

/* & явно помещается перед .circle */
.demo {
& .circle {
opacity: .25;
filter: blur(25px);
}
}

или

/* без &, только с отступом */
.demo {
.circle {
opacity: .25;
filter: blur(25px);
}
}

В результате, все элементы с классом .circle внутри .demo размыты и почти невидимы:

See the Pen

Выделение треугольников и квадратов

Эта задача требует выбора нескольких вложенных элементов, также называемых групповым селектором.

Без вложенности, в CSS сегодня есть два пути:

.demo .triangle,
.demo .square
{
opacity: .25;
filter: blur(25px);
}

или, используя :is()

/* сгруппировано с :is() */
.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}

С вложенностью есть два допустимых способа:

.demo {
& .triangle,
& .square
{
opacity: .25;
filter: blur(25px);
}
}

или

.demo {
.triangle, .square {
opacity: .25;
filter: blur(25px);
}
}

Оба варианта вложенности будут использовать :is() под капотом следующим образом.

.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}

В результате внутри .demo останутся только элементы .circle.

See the Pen

Выделение больших треугольников и кругов

Для этой задачи требуется составной селектор, в котором элементы должны иметь оба класса, чтобы их можно было выбрать.

Без вложенности CSS сегодня:

.demo .lg.triangle,
.demo .lg.square
{
opacity: .25;
filter: blur(25px);
}

или

.demo .lg:is(.triangle, .circle) {
opacity: .25;
filter: blur(25px);
}

С вложенностью два допустимых варианта:

.demo {
.lg.triangle,
.lg.circle
{
opacity: .25;
filter: blur(25px);
}
}

или

.demo {
.lg {
&.triangle,
&.circle
{
opacity: .25;
filter: blur(25px);
}
}
}

В результате все большие треугольники и круги внутри .demo скрыты:

See the Pen

Профессиональный совет с составными селекторами и вложенностью

Здесь вам поможет символ &, так как он явно показывает, как присоединяться к вложенным селекторам. Рассмотрим следующий пример:

.demo {
.lg {
.triangle,
.circle
{
opacity: .25;
filter: blur(25px);
}
}
}

Хотя это допустимый способ вложения, результаты не будут соответствовать ожидаемым элементам. Причина в том, что без & для указания желаемого результат .lg.triangle, .lg.circle, составленного вместе, фактический результат будет .lg .triangle, .lg .circle; селекторы потомков.

Примечание. Вложенные классы без & всегда приводят к селекторам потомков. Используйте символ &, чтобы изменить этот результат.

Выбор всех фигур кроме розовых

Для этой задачи требуется функциональный псевдокласс :not(), в котором элементы не должны иметь указанный селектор.

Без вложенности CSS сегодня:

.demo :not(.pink) {
opacity: .25;
filter: blur(25px);
}

С вложенностью два допустимых варианта:

.demo {
:not(.pink) {
opacity: .25;
filter: blur(25px);
}
}

или

.demo {
& :not(.pink) {
opacity: .25;
filter: blur(25px);
}
}

В результате все фигуры, не розового цвета, скрыты внутри .demo:

See the Pen

Точность и гибкость с &

Скажем, вы хотели выбрать .demo с помощью селектора :not(). & потребуется для этого:

.demo {
&:not() {
...
}
}

Это объединяет .demo и :not() в .demo:not(), в отличие от предыдущего пример, в котором требовалось .demo :not(). Это напоминание очень важно, когда вы хотите вложить взаимодействие :hover.

.demo {
&:hover {
/* .demo:hover */
}

:hover {
/* .demo :hover */
}
}

Больше примеров с вложенностью

Спецификация CSS для вложенности заполнена большим количеством примеров. Если вы хотите узнать больше о синтаксисе с помощью примеров, она охватывает широкий спектр допустимых и недопустимых примеров.

В следующих нескольких примера будет кратко представлена функция вложенности CSS, чтобы помочь понять широту возможностей, которые она предоставляет.

Вложенность @media

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

Для удобства синтаксиса, если вложенный медиа-запрос изменяет стили только для текущего контекста селектора, можно использовать минимальный синтаксис.

.card {
font-size: 1rem;

@media (width >= 1024px) {
font-size: 1.25rem;
}
}

& Также может явно использоваться:

.card {
font-size: 1rem;

@media (width >= 1024px) {
&.large {
font-size: 1.25rem;
}
}
}

В этом примере показан расширенный синтаксис &, а также нацелены на .large карты, чтобы продемонстрировать, что дополнительные функции вложения продолжают работать.

Узнайте больше о вложении @rules.

Вложения где угодно

Все примеры до этого момента были продолжены или добавлены к предыдущему контексту. При необходимости вы можете полностью изменить контекст.

.card {
.featured & {
/* .featured .card */
}
}

Символ & представляет собой ссылку на объект селектора (не строку) и может быть размещён в любом месте вложенного селектора. Его даже можно разместить несколько раз:

.card {
.featured & & & {
/* .featured .card .card .card */
}
}

Хотя этот пример выглядит немного бесполезным, безусловно, есть сценарии, в которых возможность повторения контекста селектора удобна.

Недопустимые примеры вложения

Есть несколько недопустимых сценариев вложенного синтаксиса, которые могут вас удивить, если вы применяли вложенность в препроцессорах. Шпаргалку по допустимому синтаксису вложенности можно найти в разделе Понимание парсера вложенности в этой статье.

Имена тэгов вложенных элементов

В настоящее время HTML элементы требуют наличия символа & впереди или в обёртке с помощью :is().

.card {
h1 {
/* 🛑 h1 не начинается с символа & */
}
}

Исправлено с таким синтаксисом:

.card {
& h1 {
/* ✅ теперь h1 начинается с символа & */
}

/* or */

:is(h1) {
/* ✅ теперь h1 обёрнут в :is() */
}
}
Вложение и конкатенация

Многие соглашения об именах CSS классов рассчитывают на то, что вложенность может объединять и добавлять селекторы, как если бы они были строками. Это не работает в CSS вложенности, поскольку селекторы не являются строками, это ссылки на объекты.

.card {
&--header {
/* это не равно ".card--header" */
}
}

Более подробное объяснение можно найти в спецификации

Смешивание вложенности и объявлений

Рассмотрим следующий вложенный CSS блок:

.card {
color: green;
& { color: blue; }
color: red;
}

Цвет элемента .card будет blue.

Любые объявления смешанных стилей поднимаются вверх, как если бы они были созданы до того, как произошло какое-либо вложение. Подробнее можно узнать в спецификации.

Понимание парсера вложенности

Чтобы достичь наибольшего успеха с CSS вложением, авторы могут изучить примеры из спецификации или узнать, как синтаксический анализатор CSS работает с вложением. Обладая этими знаниями авторы могут уверенно вкладывать стили, не посматривая постоянно в правила.

Первый и самый простой способ представить синтаксический анализатор — определить символы, которые сигнализируют синтаксическому анализатору, что он использует вложенность стилей.

& @ : . > ~ + # [ *

Эти символы должны выглядеть знакомыми. Некоторые из них являются комбинаторами, а некоторые предназначены для селекторов. Таким образом, в самом простом случае, если синтаксический анализатор находит ваши вложенные селекторы и они не начинаются с одного из этих символов, он потерпит неудачу и неправильно использует ваши стили.

Обнаружение возможности

Есть два отличных способа обнаружить вложенность CSS: использовать вложенность или использовать @support для проверки возможности синтаксического анализа селектора вложенности.

Использование вложенности:

html {
.has-nesting {
display: block;
}

.no-nesting {
display: none;
}
}

Использование @support

@supports (selector(&)) {
/* Парсинг вложенности доступен */
}

У моего коллега Bramus есть отличный CodePen, показывающий эту стратегию.

See the Pen

Отладка с помощью Chrome DevTools

Текущая поддержка вложенности в DevTools минимальна. В настоящее время вы обнаружите, что стили представлены на панели Стили, как и ожидалось, но отслеживание вложения и его полного контекста селектора пока не поддерживается. У нас есть дизайн и планы, чтобы сделать это прозрачным и понятным.

В Chrome 113 планируется дополнительная поддержка Вложенности CSS. Следите за обновлениями.

Будущее

CSS Nesting/Вложенность есть только в версии 1. В версии 2 будет больше синтаксического сахара и, возможно, меньше правил для запоминания. Существует много требований, чтобы парсинг вложенности не был ограничен, чтобы не было списка символов, которые активируют парсер.

Вложенность — это большое улучшение языка CSS. Это имеет отношение к разработке почти каждого архитектурного аспекта CSS. Это большое влияние необходимо тщательно изучить и понять, прежде чем можно будет эффективно определить версию 2.

В качестве заключительной мысли, вот демонстрация, использующая @scoop, вложенность и @layer все вместе. Всё это очень захватывающе!

Использование @scoop, CSS вложенности и @layer все вместе

Дополнительные материалы

Предыдущая Статья

API Аутентификация в Laravel

Следующая Статья

PHP Enum: Руководство для начинающих