Возможность запрашивать размер родительского элемента и значения единиц измерения контейнера недавно получила стабильную поддержку во всех современных браузерных движках .
Однако спецификация встраивания стилей включает в себя не только запросы по размеру; она также позволяет запрашивать значения стилей родительского элемента. Начиная с Chromium 111, вы сможете применять встраивание стилей к значениям пользовательских свойств и запрашивать значение пользовательского свойства у родительского элемента.
Browser Support
Это означает, что у нас есть еще более логичный контроль над стилями в CSS, и это позволяет лучше отделить логический и информационный слой приложения от его стилей.
Спецификация CSS Containment Module Level 3, которая описывает запросы размеров и стилей, позволяет запрашивать любые стили из родительского элемента, включая пары свойство-значение, такие как font-weight: 800 Однако в настоящее время, в процессе внедрения этой функции, запросы стилей работают только со значениями пользовательских свойств CSS. Это по-прежнему очень полезно для объединения стилей и отделения данных от дизайна. Давайте посмотрим, как использовать запросы стилей с пользовательскими свойствами CSS:
Начало работы с запросами по стилю
Допустим, у нас есть следующий HTML-код:
<ul class="card-list">
<li class="card-container">
<div class="card">
...
</div>
</li>
</ul>
Для использования стилевых запросов необходимо сначала настроить элемент-контейнер. Это требует несколько иного подхода в зависимости от того, обращаетесь ли вы к прямому или косвенному родительскому элементу.
Запрос к непосредственным родителям

В отличие от запросов стилей, вам не нужно применять контейнеризацию с помощью свойства container-type или container к .card-container чтобы .card мог запрашивать стили своего непосредственного родительского элемента. Однако нам необходимо применять стили (в данном случае значения пользовательских свойств) к контейнеру (в данном случае .card-container ) или любому элементу, содержащему элемент, который мы стилизуем в DOM. Мы не можем применять запрашиваемые стили к непосредственному элементу, который мы стилизуем с помощью этого запроса, поскольку это может привести к бесконечным циклам.
Для прямого запроса к родительскому элементу можно написать:
/* styling .card based on the value of --theme on .card-container */
@container style(--theme: warm) {
.card {
background-color: wheat;
border-color: brown;
...
}
}
Возможно, вы заметили, что запрос стиля оборачивается функцией style() . Это позволяет различать значения размера и стили. Например, вы можете написать запрос для ширины контейнера следующим образом: @container (min-width: 200px) { … } . Это применит стили, если ширина родительского контейнера составляет не менее 200 пикселей. Однако ` min-width также может быть свойством CSS, и вы можете запросить значение ` min-width с помощью запросов стиля. Именно поэтому используется обертка style() , чтобы сделать разницу очевидной: @container style(min-width: 200px) { … } .
Стилистические услуги для непрямых родителей
Если вы хотите задать стили для любого элемента, который не является его непосредственным родительским элементом, вам необходимо указать этому элементу container-name . Например, мы можем применить стили к элементу .card на основе стилей элемента .card-list , указав элементу .card-list container-name и сославшись на него в запросе стилей.
/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
.card {
...
}
}
Как правило, рекомендуется присваивать контейнерам имена, чтобы было понятно, к чему именно вы обращаетесь, и чтобы упростить доступ к этим контейнерам. Примером полезности может служить стилизация элементов непосредственно внутри .card . Без именованного контейнера для .card-container , обращаться к нему напрямую будет невозможно.
Но на практике всё это имеет гораздо больше смысла. Давайте рассмотрим несколько примеров:
Вопросы стиля на практике

Запросы стилей особенно полезны, когда у вас есть многократно используемый компонент с несколькими вариантами или когда вы не контролируете все стили, но вам необходимо вносить изменения в определенных случаях. В этом примере показан набор карточек товаров, которые используют один и тот же компонент. Некоторые карточки товаров имеют дополнительные сведения/примечания, такие как «Новинка» или «Мало на складе», которые активируются пользовательским свойством с именем --detail . Кроме того, если товар находится в состоянии «Мало на складе», он получает темно-красную рамку. Этот тип информации, скорее всего, отображается на сервере и может быть применен к карточкам с помощью встроенных стилей следующим образом:
<div class="product-list">
<div class="product-card-container" style="--detail: new">
<div class="product-card">
<div class="media">
<img .../>
<div class="comment-block"></div>
</div>
</div>
<div class="meta">
...
</div>
</div>
<div class="product-card-container" style="--detail: low-stock">
...
</div>
<div class="product-card-container">
...
</div>
...
</div>
Имея эти структурированные данные, вы можете передавать значения параметру --detail и использовать это пользовательское свойство CSS для применения стилей:
@container style(--detail: new) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'New';
border: 1px solid currentColor;
background: white;
...
}
}
@container style(--detail: low-stock) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'Low Stock';
border: 1px solid currentColor;
background: white;
...
}
.media-img {
border: 2px solid brickred;
}
}
Приведённый выше код позволяет применять модификаторы для --detail: low-stock и --detail: new , но вы могли заметить некоторую избыточность в этом блоке кода. В настоящее время нет возможности запросить только наличие --detail с помощью @container style(--detail) , что позволило бы лучше использовать общие стили и уменьшить повторение. Эта возможность в настоящее время обсуждается в рабочей группе.
Карточки погоды
В предыдущем примере использовалось одно пользовательское свойство с несколькими возможными значениями для применения стилей. Но вы можете разнообразить подход, используя и запрашивая несколько пользовательских свойств одновременно. Возьмем, к примеру, карточку погоды:

Для оформления фоновых градиентов и значков на этих карточках используйте характеристики погоды, такие как «облачно», «дождливо» или «солнечно»:
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
Таким образом, вы можете стилизовать каждую карточку в соответствии с её уникальными характеристиками. Но вы также можете стилизовать её для комбинаций характеристик (пользовательских свойств), используя комбинатор ` and так же, как и для медиа-запросов . Например, день, когда одновременно облачно и солнечно, будет выглядеть так:
@container style(--sunny: true) and style(--cloudy: true) {
.weather-card {
background: linear-gradient(24deg, pink, violet);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: violet;
}
}
Разделение данных и проектирования
В обоих этих примерах есть структурное преимущество разделения слоя данных (DOM, который будет отображаться на странице) от применяемых стилей. Стили записываются как возможные варианты, которые находятся внутри стиля компонента, в то время как конечная точка может отправлять данные, которые затем будут использоваться для стилизации компонента. Вы можете использовать одно значение, как в первом случае, обновляя значение --detail , или несколько переменных, как во втором случае (устанавливая либо --rainy , --cloudy , либо --sunny . И самое приятное, что вы также можете комбинировать эти значения, проверяя одновременно --sunny и --cloudy что может отобразить стиль частично облачного освещения.
Обновление значений пользовательских свойств с помощью JavaScript можно выполнить без проблем, либо во время настройки модели DOM (т.е. при создании компонента во фреймворке), либо в любое время, используя <parentElem>.style.setProperty('--myProperty', <value>) .
Вот демонстрационный пример, который всего несколькими строками кода обновляет параметр --theme кнопки и применяет стили, используя запросы стилей и это пользовательское свойство ( --theme ):
Оформите карточку с помощью стилевых запросов; для обновления значений пользовательских свойств используется следующий JavaScript-код:
const themePicker = document.querySelector('#theme-picker')
const btnParent = document.querySelector('.btn-section');
themePicker.addEventListener('input', (e) => {
btnParent.style.setProperty('--theme', e.target.value);
})
Функции, подробно описанные в этой статье, — это только начало. Вы можете ожидать от запросов контейнера и других возможностей, которые помогут вам создавать динамичные, адаптивные интерфейсы. Что касается запросов стилей, то здесь еще есть несколько открытых вопросов. Один из них — реализация запросов стилей для CSS-стилей, выходящих за рамки пользовательских свойств. Это уже часть текущего уровня спецификации, но пока не реализовано ни в одном браузере. Ожидается, что логическая оценка контекста будет добавлена в текущий уровень спецификации после решения этой нерешенной проблемы , а запросы диапазона планируются на следующий уровень спецификации.