CSS следующего поколения: @container

CSS следующего поколения: @container

От автора: Chrome экспериментирует со свойством @container в рамках спецификации уровня ограничения 3 рабочей группы CSS, над которой работают Мириам Сюзанн из Oddbird и группа инженеров по веб-платформе. @container дает нам возможность стилизовать элементы в зависимости от размера их родительского контейнера.

@containerAPI не является стабильным, и подлежит изменениям синтаксиса. Если вы попробуете его самостоятельно, вы можете столкнуться с несколькими ошибками. Пожалуйста, сообщайте об этих ошибках разработчикам браузера!

Вы можете думать об @container как о медиа-запросе (@media), но вместо того, чтобы полагаться на область просмотра для настройки стилей, родительский контейнер элемента, на который вы нацеливаетесь, может настраивать эти стили.

Запросы контейнеров станут самым большим изменением в веб-стилях со времен CSS3, изменив наше представление о том, что означает «адаптивный дизайн».

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

@container в действии

В этом примере я использую две карточки в родительском элементе со следующей разметкой:

<div class="card-container"> <div class="card"> <figure> ... </figure> <div> <div class="meta"> <h2>...</h2> <span class="time">...</span> </div> <div class="notes"> <p class="desc">...</p> <div class="links">...</div> </div> <button>...</button> </div> </div>
</div>

Затем я устанавливаю ограничение (свойство contain) для родительского элемента, для которого я буду запрашивать стили контейнера (.card-container). Я также устанавливаю относительный макет сетки для родительского элемента .card-container; и его inline-size будет меняться в зависимости от этой сетки. Это то, что я запрашиваю через @container:

.card-container { contain: layout inline-size; width: 100%;
}

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

/* when the parent container is smaller than 850px, remove the .links div and decrease the font size on the episode time marker */ @container (max-width: 850px) { .links { display: none; } .time { font-size: 1.25rem; } /* ... */
} /* when the parent container is smaller than 650px, decrease the .card element's grid gap to 1rem */ @container (max-width: 650px) { .card { gap: 1rem; } /* ... */
}

Контейнерные запросы + медиа-запросы

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

Вот еще один пример, демонстрирующий возможности использования медиа-запросов для макета макроса (т. е. перехода календаря от однопанельного к многопанельному) и микромакета (т. е. макета / размера даты и смещения полей / размера событий) для создания совокупности запросов.

Контейнерные запросы + CSS-сетка

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

На этом сайте вообще не используются медиа-запросы. Вместо этого мы используем только контейнерные запросы вместе с сеткой CSS для отображения компонента карточки покупок в разных представлениях.

В таблице продуктов макет создается с помощью grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));. Это создает макет, который сообщает карточкам, что они должны занимать доступное дробное пространство, пока они не достигнут своего размера 230px, а затем переходить к следующей строке.

Затем у нас есть контейнерный запрос, который стилизует карточки, чтобы они принимали вертикальный блочный макет, когда они меньше ширины 350px, и переходит к горизонтальному встроенному макету путем применения display: flex.

@container (min-width: 350px) { .product-container { padding: 0.5rem 0 0; display: flex; } /* ... */
}

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

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

Чтобы использовать @container, вам сначала нужно создать родительский элемент, у которого есть ограничение . Для этого вам нужно установить родительский contain: layout inline-size. Вы можете использовать inline-size, поскольку в настоящее время мы можем применять контейнерные запросы только к встроенной оси. Это предотвращает разрыв вашего макета в направлении блоков.

Настройка contain: layout inline-size создает новый ограничивающий блок и новый контекст форматирования блока, позволяя браузеру отделить его от остальной части макета. Теперь мы можем перейти к запросам!

Ограничения

В настоящее время нельзя использовать контейнерные запросы на основе высоты, используя только ось блока. Чтобы заставить сетку элементов наследников работать @container, вам нужно добавить элемент оболочки. Основываясь на этом, добавление оболочки позволяет получить желаемые эффекты.

Попробуйте его

Вы можете поэкспериментировать со свойством @container уже сегодня, перейдя по адресу: chrome://flags в Chrome Canary и включив флаг #experimental-container-queries.

CSS следующего поколения: @container

Автор: Una Kravets

Источник: css-tricks.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен