От автора: Chrome экспериментирует со свойством @container в рамках спецификации уровня ограничения 3 рабочей группы CSS, над которой работают Мириам Сюзанн из Oddbird и группа инженеров по веб-платформе. @container дает нам возможность стилизовать элементы в зависимости от размера их родительского контейнера.
@containerAPI не является стабильным, и подлежит изменениям синтаксиса. Если вы попробуете его самостоятельно, вы можете столкнуться с несколькими ошибками. Пожалуйста, сообщайте об этих ошибках разработчикам браузера!
Вы можете думать об @container как о медиа-запросе (@media), но вместо того, чтобы полагаться на область просмотра для настройки стилей, родительский контейнер элемента, на который вы нацеливаетесь, может настраивать эти стили.
Запросы контейнеров станут самым большим изменением в веб-стилях со времен CSS3, изменив наше представление о том, что означает «адаптивный дизайн».
Область просмотра и пользовательский агент больше не будут единственными целями, которые нам нужны для создания адаптивного макета и стилей пользовательского интерфейса. С помощью контейнерных запросов элементы смогут влиять на своих родителей и соответственно применять свои собственные стили. Это означает, что один и тот же элемент, который находится в боковой панели, в теле или заголовке, может выглядеть совершенно по-разному в зависимости от доступного ему размера и динамики.
@container в действии
В этом примере я использую две карточки в родительском элементе со следующей разметкой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<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:
1 2 3 4 |
.card-container { contain: layout inline-size; width: 100%; } |
Теперь я могу запросить стили контейнера, чтобы установить стили! Это очень похоже на то, как вы устанавливаете стили с помощью медиа-запросов на основе ширины, используя max-width для установки стилей, когда элемент меньше определенного размера, а min-width когда он больше.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* 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.
1 2 3 4 5 6 7 8 |
@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.
Автор: Una Kravets
Источник: css-tricks.com
Редакция: Команда webformyself.
Читайте нас в Telegram, VK, Яндекс.Дзен