Использование запросов размера и стиля контейнера
Базовая версия 2023
Новое
Начиная с февраля 2023 года, эта функция работает на последних версиях устройств и браузеров. Возможно, эта функция не будет работать на более старых устройствах или браузерах.
Запросы контейнеров позволяют применять стили к элементам, вложенным в определенный контейнер, на основе свойств этого контейнера. Запрос возвращает true или false в зависимости от того, выполняется ли условие запроса для контейнера.
Запросы контейнеров похожи на запросы среды. Правило @media позволяет применять стили к элементам на основе размера области просмотра или других характеристик устройства. Аналогично, правило @container позволяет применять стили к элементам на основе размера или других стилевых свойств содержащего элемента, а не области просмотра. Запросы контейнеров имеют те же правила синтаксиса и логические операторы, что и запросы среды.
@container <container-condition># {
/* <stylesheet> */
}
Существует два типа запросов контейнеров: запросы размера контейнера и запросы стиля контейнера:
- Запросы размера контейнера
-
Запросы размера позволяют применять стили к элементам на основе текущего размера содержащего элемента, включая ориентацию и отношение сторон. Содержимые элементы должны быть явно объявлены как контейнеры запроса размера.
- Запросы стиля контейнера
-
Запросы стиля позволяют применять стили к элементам на основе стилевых свойств содержащего элемента. Любой непустой элемент может быть контейнером запроса стиля. В настоящее время единственное стилевое свойство, поддерживаемое запросами стиля, — это пользовательские свойства CSS. В этом случае запрос возвращает true или false в зависимости от вычисленного значения пользовательских свойств содержащего элемента. При полной поддержке запросов стиля контейнера вы сможете применять стили к потомкам любого элемента на основе любого свойства, объявления или вычисленного значения — например, если контейнер
display: inline flexили имеет непрозрачный цвет фона.
В этом руководстве мы изучаем основы запросов контейнеров, рассматривая:
- запросы размера контейнера,
- названия контейнеров для ограничения их области действия, и
- использование функциональной нотации
style()в правиле@container<container-condition>для создания запросов стиля с пользовательскими свойствами.
Запросы размера контейнера
Запросы размера контейнера фильтруются по условию размера. Соответствующие стили применяются к содержащим элементам, если элемент контейнера объявлен как контейнер, и условие контейнера истинно для этого элемента. Контейнер размера элемента — ближайший предок с контейнментом.
Элементы объявляются как контейнеры запроса размера, установив их свойство container-type (или сокращенное свойство container) в size или inline-size.
@container (orientation: landscape) {
/* styles applied to descendants of this size container */
}
.sizeContainer {
container-type: size;
}
Объявление контейнеров запроса размера добавляет контейнмент к ним. Это необходимо для производительности — запрос размера каждого элемента в DOM постоянно наносит вред производительности и пользовательскому опыту. Кроме того, если дочерний стиль изменил размер элемента контейнера, может произойти бесконечный цикл.
В запросе размера контейнера <container-condition> содержит один или несколько <size-query>. Каждый запрос размера включает имя свойства размера, оператор сравнения и значение. Свойства размера, которые можно запросить, ограничены width, height, inline-size, block-size, aspect-ratio, и orientation. Логика булевых выражений и комбинация одного или нескольких <size-query> такая же, как у запросов свойств размера @media.
form {
container-type: inline-size;
}
@container (10em <= width <= 20em) {
/* styles */
}
<container-condition> в этом примере содержит один <size-query> — (10em <= width <= 20em). В этом случае все <form> элементы являются потенциальными совпадениями для любого неопределенного запроса контейнера. Стиль, объявленный в запросе контейнера, применяется к потомкам всех форм от 10em до 30em шириной, включительно.
Наименование контейнеров
<container-condition> может включать необязательное чувствительное к регистру container-name. Имя контейнера делает условие контейнера более специфичным — оно оценивается только для элементов, у которых это имя установлено в свойстве container-name.
Свойство container-name определяет список значений запроса <container-name> , которые могут быть использованы в правилах @container; это чувствительные к регистру <ident> значения. Имена контейнеров позволяют нацеливаться на любой контейнер-предок элемента. Без имени контейнера запрос соответствует только ближайшему контейнер-предку.
@container [ [ <container-name> ]? <container-query> ]# {
/* <stylesheet> */
}
После добавления имен к вашим правилам @container at-rule, вы можете использовать свойство container-name или сокращенное свойство container для нацеливания на определенные элементы контейнера. Стиль внутри правил @container at-rule будет применяться только к соответствующим элементам внутри контейнеров с установленными именами, которые удовлетворяют запросам контейнеров.
@container card (orientation: landscape) {
/* styles */
}
.todo-panel > li {
container-type: inline-size;
container-name: card;
}
В приведенном выше примере стили внутри блока запроса контейнера будут применяться к потомкам всех <li> элементов с шириной, большей, чем высота. Обратите внимание, что и другие элементы, к которым применено container-name: card и которые соответствуют запросу размера, также получат эти стили для своих потомков.
@container wide (min-width: 20em) {
/* styles applied to descendants of wide .sizeContainer */
}
@container narrow (max-width: 20em) {
/* styles applied to descendants of narrow .sizeContainer */
}
.sizeContainer {
container-type: size;
container-name: wide narrow;
}
В приведенном выше примере элемент имеет два имени контейнера, wide и narrow. Потомки любых элементов с class="sizeContainer" получат стили из запроса wide или narrow (или обоих, если элемент имеет ровно 20em ширины).
Значение по умолчанию container-type: normal предотвращает контейнер от того, чтобы быть контейнером размера, но он все еще может быть контейнером стиля. Значение по умолчанию container-name: none означает, что контейнер не имеет имени, но это не предотвращает элемент от соответствия неопределенным запросам.
С запросами контейнеров мы не ограничены запросами размера! Вы также можете запросить стилевые особенности контейнера.
Запросы стилей контейнера
Запрос стиля контейнера — это @container запрос, который оценивает вычисленные стили элемента-контейнера, как определено в одном или нескольких style() функциональных обозначениях. Булевы синтаксис и логика, используемые для объединения свойств стиля в запрос стиля, такие же, как в запросах свойств CSS. Единственное отличие — имя функции — style() внутри <style-feature> по сравнению с supports() внутри <support-condition>.
@container style(<style-feature>),
not style(<style-feature>),
style(<style-feature>) and style(<style-feature>),
style(<style-feature>) or style(<style-feature>) {
/* <stylesheet> */
}
Параметр каждой функции style() — единственный <style-feature>. Согласно спецификации CSS containment, <style-feature> может быть допустимым CSS объявлением, свойством CSS или <custom-property-name>. В настоящее время поддерживается только свойство пользовательского свойства с или без значения. См. таблицу совместимости браузеров.
Если <style-feature> включает значение, запрос стиля оценивается как истинное, если вычисленное значение пользовательского свойства (или, в будущем, объявления CSS), переданное в качестве параметра style(), истинно для контейнера, который запрашивается. В противном случае он разрешается как ложно. Свойство стиля без значения оценивается как истинное, если вычисленное значение отличается от начального значения для данного свойства.
В будущем мы сможем писать запросы стиля следующим образом:
@container style(color: green) and style(background-color: transparent),
not style(background-color: red),
style(--themeBackground),
style(--themeColor: blue) or style(--themeColor: purple),
(max-width: 100vw) and style(max-width: 600px) {
/* <stylesheet> */
}
Функциональное обозначение style() используется для различения запросов стиля от запросов размера. Хотя пока это не поддерживается, в конечном итоге мы сможем запросить обычные объявления CSS, такие как max-width: 100vw. Запрос @container (max-width: 100vw) — это запрос размера; для containment требуется container-type или сокращённая запись container. Этот запрос вернет true, если контейнер имеет размер 100vw или меньше. Это отличается от запроса @container style(max-width: 100vw), который является запросом стиля; при поддержке этот запрос вернёт true, если у контейнера есть значение max-width равное 100vw.
До тех пор, пока запросы стиля для обычных объявлений и свойств CSS не будут поддерживаться, мы ограничены включением только пользовательских свойств в качестве параметра style(), с или без значения:
@container style(--themeBackground),
style(--themeColor: blue) or style(--themeColor: purple) {
/* <stylesheet> */
}
Несколько моментов, которые уже упоминались, но важно помнить:
- Все элементы могут быть контейнерами запроса стиля; установка
container-typeне требуется. Когда дочерние стили не влияют на вычисленные стили предка, containment не требуется. - Запрос
<container-condition>может включать как свойства стиля, так и размера. Если в вашем запросе есть свойства размера, убедитесь, что ваши элементы-контейнеры имеютcontainer-typeзначениеsizeилиinline-size. - Если вы не хотите, чтобы элемент считался контейнером, задайте ему
container-nameзначение, которое не будет использоваться. Установкаcontainer-name: noneудаляет любые имена запросов, связанные с контейнером; это не предотвращает элемент от того, чтобы он был контейнером стиля. - На момент написания (февраль 2024 г.) запросы стиля контейнера работают только с значениями пользовательских свойств CSS в запросе
style().
Теперь давайте углубимся и рассмотрим различные типы <style-feature>.
Запросы стилей для пользовательских свойств
Запросы стилей для пользовательских свойств позволяют вам запросить пользовательские свойства (также называемые "переменными CSS") родительского элемента. Они включаются в <style-query> так же, как вы включаете любое обычное свойство CSS в запросе к функции: с значением или без него.
Самостоятельные запросы к пользовательским свойствам
Параметр <style-query> функциональной нотации style() может содержать только имя переменной CSS; пользовательское свойство без значения. Если значение не указано, запрос вернёт false, если значение совпадает со значением дескриптора initial-value в @property атрибуте, если такой есть. Запрос стиля вернёт true и соотнесётся со всеми элементами, имеющими значение пользовательского свойства, отличное от initial-value, или со всеми элементами, имеющими любое значение пользовательского свойства, если пользовательское свойство было объявлено без регистрации.
Незарегистрированные пользовательские свойства
Когда переменные CSS вводятся через простое присвоение значения пользовательскому свойству CSS, запросы к пользовательским свойствам без значения всегда возвращают true.
:root {
--theme-color: rebeccapurple;
}
@container style(--theme-color) {
/* <stylesheet> */
}
В этом примере запрос к контейнеру соответствует элементу, в котором было объявлено свойство --theme-color, и всем его потомкам. Поскольку переменная CSS --theme-color была объявлена в элементе :root, запрос стиля style(--theme-color) будет истинным для каждого элемента внутри этого узла DOM.
Зарегистрированные свойства
Поведение зарегистрированных пользовательских свойств отличается. Если они явно определены с помощью CSS-правила @property или через JavaScript с помощью метода CSS.registerProperty(), запрос стиля style(--theme-color) вернёт true только для элементов, если вычисленное значение элемента для --theme-color отличается от initial-value, установленного в исходном определении этого пользовательского свойства.
@property --theme-color {
initial-value: rebeccapurple;
inherited: true;
}
:root {
--theme-color: rebeccapurple;
}
main {
--theme-color: blue;
}
@container style(--theme-color) {
/* <stylesheet> */
}
В этом примере элемент :root НЕ соответствует запросу стиля, потому что значение пользовательского свойства совпадает со значением initial-value. Значение пользовательского свойства для элемента (и всех элементов, наследующих это значение) всё ещё равно rebeccapurple. Совпадением будут только элементы, отличающиеся от начального значения, в данном случае <main> и его потомки, унаследовавшие изменённое значение.
Пользовательское свойство со значением
Если запрос стиля включает значение для пользовательского свойства, вычисленное значение свойства элемента должно быть точным совпадением. Эквивалентные значения будут совпадать только если пользовательское свойство было определено с помощью правила @property (или вызова метода CSS.registerProperty()) содержащего дескриптор syntax.
@container style(--accent-color: blue) {
/* <stylesheet> */
}
Этот запрос стиля к контейнеру соответствует любому элементу, у которого blue является computed_value пользовательского свойства --accent-color.
В этом случае другие цветовые значения, эквивалентные sRGB blue (например, шестнадцатеричный код #0000ff) будут совпадать только если свойство --accent-color было определено как цвет с дескрипторами @property или CSS.registerProperty(), например:
@property --accent-color {
syntax: "<color>";
inherits: true;
initial-value: #00f;
}
В этом случае, если значение --accent-color было бы установлено в blue, #00f, #0000ff, rgb(0 0 255 / 1) или rgb(0% 0% 100%), это вернуло бы true для @container style(--accent-color: blue).
Пример
В этом примере у нас есть <fieldset> с четырьмя радиокнопками. Четвёртый вариант включает текстовое <input> для ввода пользовательского цвета.
<fieldset>
<legend>Change the value of <code>--theme</code></legend>
<ol>
<li>
<input type="radio" name="selection" value="red" id="red" />
<label for="red">--theme: red;</label>
</li>
<li>
<input type="radio" name="selection" value="green" id="green" />
<label for="green">--theme: green</label>
</li>
<li>
<input type="radio" name="selection" value="blue" id="blue" />
<label for="blue">--theme: blue</label>
</li>
<li>
<input type="radio" name="selection" value="currentcolor" id="other" />
<label for="other">Other</label>
<label for="color">color:</label>
<input text="checkbox" name="selection" value="currentcolor" id="color" />
</li>
</ol>
</fieldset>
<output>I change colors</output>
JavaScript обновляет значение CSS-переменной --theme элемента <body>, который является предком элементов <fieldset> и <output>, всякий раз, когда выбирается радиокнопка. Когда текст <input> обновляется, value радиокнопки other обновляется только в том случае, если выбрана радиокнопка other, что, в свою очередь, обновляет значение --theme.
const radios = document.querySelectorAll('input[name="selection"]');
const body = document.querySelector("body");
const other = document.getElementById("other");
const color = document.getElementById("color");
for (let i = 0; i < radios.length; i++) {
radios[i].addEventListener("change", (e) => {
body.style.setProperty("--theme", e.target.value);
});
}
color.addEventListener("input", (e) => {
other.style.setProperty("value", e.target.value);
if (other.checked) {
body.style.setProperty("--theme", e.target.value);
}
});
Мы используем правило @property для определения CSS-переменной --theme как <color> значения и устанавливаем initial-value в #00F, обеспечивая соответствие эквивалентных цветов независимо от используемой синтаксической конструкции (например, #F00 равно rgb(255 0 0), #ff0000 и red).
@property --theme {
syntax: "<color>";
inherits: true;
initial-value: #f00;
}
Первый запрос к стилю — это пользовательское свойство без значения. Этот тип запроса возвращает true, когда вычисленное значение для значения пользовательского свойства отличается от initial-value этого свойства. В данном случае это будет true, когда значение --theme будет любым значением, отличным от любого синтаксически эквивалентного значения #f00 (такого как red). В случае истинности, у <output> будет пунктирная рамка 5 пикселей. Цвет рамки — текущее значение --theme. По умолчанию цвет текста color — серый.
@container style(--theme) {
output {
outline: 5px dotted var(--theme);
color: #777;
}
}
Второй и третий запросы к стилю включают значения для пользовательского свойства. Они будут соответствовать, если значение --theme контейнера эквивалентно указанному значению, даже если это значение совпадает с initial-value. Первый запрос соответствует элементам, значение --theme которых эквивалентно red, blue или green. В этом случае цвет color будет цветом текущего значения --theme (в случае с blue и green, переопределяя серый, установленный в первом запросе к стилю).
Второй запрос к стилю гласит, что когда --theme эквивалентно red, содержимое <output> также будет полужирным. Мы сделали это, чтобы лучше продемонстрировать, что запрос к контейнеру — это совпадение.
@container style(--theme: green) or style(--theme: blue) or style(--theme: red) {
output {
color: var(--theme);
}
}
@container style(--theme: red) {
output {
font-weight: bold;
}
}
Попробуйте ввести разные цветовые значения в текстовое поле. Вы можете заметить, что значения, являющиеся sRGB-эквивалентами red, сделают <output> красным — поскольку они совпадают с style(--theme: red) — и удалят рамку, потому что style(--theme) возвращает false, если значение элемента для --theme совпадает с начальным значением для --theme, определённым правилом @property. Любое некрасное sRGB-значение, включая currentcolor или hsl(180 100% 50%), и т. д., приводит к тому, что первый запрос стиля возвращает true; это значения, отличные от initial-value.
Поскольку мы установили syntax: "<color>";, переменной CSS можно назначать только допустимые <color> значения. Допустимые значения для свойства color, которые не являются значениями <color>, такими как unset или inherit, являются недопустимыми для этого пользовательского свойства и будут проигнорированы.
Если вы введёте unset или gibberish, JavaScript обновит style элемента <body> до --theme: unset или --theme: gibberish. Ни одно из них не является цветом. Оба являются недопустимыми и будут проигнорированы. Это означает, что начальное значение унаследовано и не изменилось, при этом style(--theme) возвращает false, а style(--theme: red) — true.
Примечание: При объявлении пользовательских свойств рекомендуется использовать @property с дескриптором syntax, чтобы браузер мог правильно сравнивать вычисленные значения.
Вложенные запросы
Запросы к контейнерам могут быть вложены в другие запросы к контейнерам. Стили, определённые внутри нескольких вложенных запросов к контейнерам, применяются, когда все окружающие запросы к контейнерам истинны.
@container style(--theme: red) {
output {
outline: 1px dotted;
}
@container style(--theme: purple) {
output {
outline: 5px dotted;
}
}
}
В данном случае <output> будет иметь пунктирную рамку 5 пикселей, если она вложена в контейнер, где --theme: purple установлено, и этот контейнер вложен в контейнер, значение --theme которого равно red.
Запросы стилей CSS-объявления и свойства
Пока не поддерживается ни одним браузером, функциональная запись style() может включать обычные CSS-объявления, включая CSS-свойства и пары свойство-значение.
@container style(font-weight: bold) {
b,
strong {
background: yellow;
}
}
При поддержке этот базовый пример сделает цвет фона любого элемента <b> и <strong> жёлтым, когда родительский элемент уже bold.
Сопоставление выполняется по вычисленному значению родительского контейнера; если вычисленное font-weight родительского элемента равно bold (не bolder или 900), происходит совпадение. Так же, как и с запросами стилей контейнеров, нам не нужно было определять какие-либо элементы как контейнеры стилей, так как все элементы по умолчанию являются контейнерами стилей. Пока элемент не имеет container-name задано, если у него установлено font-weight: bold или унаследовано, он будет соответствовать.
Функции стилей, которые запрашивают сокращённое свойство, будут истинными, если вычисленные значения совпадают для каждого из его длинных свойств, и ложными в противном случае. Например, @container style( будет разрешено в «истинно», если все 12 длинных свойств (border: 2px solid red)border-bottom-style и т.д.), составляющие это сокращённое свойство, установлены на одинаковые эквивалентные значения.
Глобальные CSS-значения revert и revert-layer являются недопустимыми значениями в <style-feature> и приводят к тому, что запрос стиля контейнера будет ложным.
Не применяйте стили, которые вы запрашиваете в запросе стиля, к элементу, который вы стилизуете с помощью этого запроса, так как это может привести к бесконечной петле.
Ожидается, что запросы стилей также будут принимать свойства в контексте булевых значений. Запрос стиля вернёт ложное значение, если значение свойства является начальным значением для этого свойства (если оно не было изменено), и истинное значение в противном случае.
@container style(font-weight) {
}
Вышеприведённый пример вернёт «истинно» для любого элемента, у которого есть значение для font-weight , отличное от его начального значения. Стили пользовательского агента устанавливают font-weight: bold для заголовков и <th> элементов, например. Некоторые браузеры устанавливают <strong> и <b> в bold, другие в bolder. <optgroup> также иногда имеет font-weight значение отличное от normal , установленное пользовательским агентом. Пока значение font-weight элемента не является значением по умолчанию для этого пользовательского агента, запрос стиля вернёт «истинно».
Эти функции пока не поддерживаются ни одним браузером.
Спецификации
| Спецификация |
|---|
| Модуль CSS условных правил уровня 5 # container-rule |
Совместимость с браузерами
| Рабочий стол | Мобильные устройства | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox для Android | Opera Android | Safari на IOS | Samsung Internet | WebView Android | |
Container_size_and_style_queries |
105 | 105 | 110 | 91 | 16 | 105 | 110 | 72 | 16 | 20.0 | 105 |
style_queries_for_custom_properties |
111 | 111 | Нет | 97 | 18Элемент документа не может быть контейнером. См. ошибку 271040. |
111 | Нет | 75 | 18Элемент документа не может быть контейнером. См. ошибку 271040. |
22.0 | 111 |
См. также
- Средние запросы
- CSS
@containerдиректива - CSS
containсвойство - CSS
containerсокращённое свойство - CSS
container-nameсвойство - Понимание
aspect-ratio - Начало работы с запросами стилей (2022)
- Запросы стилей via una.im (2022)
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_size_and_style_queries