Кратко
СкопированоДиректива @container включает «контейнерные запросы» — условные правила, которые зависят от размеров (и стилей) ближайшего контейнера, а не от размеров вьюпорта. Это делает компоненты по‑настоящему адаптивными и независимыми от общего макета.
Пример
Скопировано
<div class="cards" aria-label="Список карточек"> <article class="card">Карточка 1</article> <article class="card">Карточка 2</article> <article class="card">Карточка 3</article> <article class="card">Карточка 4</article> <article class="card">Карточка 5</article></div>
<div class="cards" aria-label="Список карточек">
<article class="card">Карточка 1</article>
<article class="card">Карточка 2</article>
<article class="card">Карточка 3</article>
<article class="card">Карточка 4</article>
<article class="card">Карточка 5</article>
</div>
/* Объявляем контейнер: измеряем его inline‑ось (ширину в LTR/RTL) */.cards { container-type: inline-size; display: grid; gap: 12px; grid-template-columns: repeat(3, 1fr);}/* Когда контейнер сужается, меняем компоновку — компонент адаптируется сам по себе */@container (max-width: 600px) { .cards { grid-template-columns: repeat(2, 1fr); }}@container (max-width: 380px) { .cards { grid-template-columns: 1fr; }}
/* Объявляем контейнер: измеряем его inline‑ось (ширину в LTR/RTL) */
.cards {
container-type: inline-size;
display: grid;
gap: 12px;
grid-template-columns: repeat(3, 1fr);
}
/* Когда контейнер сужается, меняем компоновку — компонент адаптируется сам по себе */
@container (max-width: 600px) {
.cards { grid-template-columns: repeat(2, 1fr); }
}
@container (max-width: 380px) {
.cards { grid-template-columns: 1fr; }
}
Как пишется
СкопированоКонтейнерный запрос срабатывает только в пределах контейнера. Чтобы он заработал, нужно:
- Объявить контейнер на элементе‑родителе компонентов.
.wrapper { container-type: inline-size; /* измерять только inline‑размер */ /* или */ /* container-type: size; измерять и inline, и block размеры */}
.wrapper {
container-type: inline-size; /* измерять только inline‑размер */
/* или */
/* container-type: size; измерять и inline, и block размеры */
}
- По желанию дать контейнеру имя и ссылаться на него в
@container:
.wrapper { container-name: layout; container-type: inline-size; }@container layout (min-width: 700px) { /* правила для компонентов внутри .wrapper */}
.wrapper { container-name: layout; container-type: inline-size; }
@container layout (min-width: 700px) {
/* правила для компонентов внутри .wrapper */
}
- Писать условия как в
@media, но измеряется именно контейнер:
@container (min-width: 480px) { /* ... */ }@container (width > 30rem) { /* диапазонный синтаксис */ }@container style(--ui: compact) { /* стилевые запросы по вычисленным стилям */ }
@container (min-width: 480px) { /* ... */ }
@container (width > 30rem) { /* диапазонный синтаксис */ }
@container style(--ui: compact) { /* стилевые запросы по вычисленным стилям */ }
Поддерживаются типы контейнеров:
inline— учитывает только ширину по inline‑оси;- size size— учитывает и ширину, и высоту;normal— отключает контейнер.
Важно: контейнер не может участвовать в размерах своих потомков, от которых он сам зависит (цикл измерений). Обычно достаточно задать «изоляцию» размеров через блок‑контекст форматирования (например, display) или явно управлять размерами.
Как понять
Скопировано@container решает классическую проблему адаптивности компонентов: ваш виджет может жить в сайдбаре и в контентной колонке, а меняться он должен по ширине своего родителя, а не окна. Теперь «точки перелома» описываются около компонента и работают в любом контексте вёрстки.
Контейнерные запросы дополняют, но не заменяют @media: первые — про локальную компоновку, вторые — про глобальную.
Подсказки
Скопировано💡 Всегда объявляйте контейнер на ближайшем родителе компонента (container). Без этого @container не сработает.
💡 Используйте имена контейнеров (container), когда на странице несколько контейнеров и правила не должны пересекаться.
💡 Храните брейкпоинты рядом с компонентом — так проще сопровождать дизайн‑систему.
💡 Для производительности избегайте слишком глубоких деревьев с множеством контейнеров без необходимости.
- Chrome 105, поддерживается
- Edge 105, поддерживается
- Firefox 110, поддерживается
- Safari 16, поддерживается