Главная » Статьи » Скажите привет контейнерным запросам CSS

Скажите привет контейнерным запросам CSS

Скажите привет контейнерным запросам CSS

От автора: сегодня я более взволнован новой функциональностью CSS, чем когда либо за последние шесть лет, которые я провел в качестве фронтенд-разработчика. Прототип контейнерных запросов теперь доступен в Chrome Canary.

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

Проблема с медиа-запросами CSS

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

Часто отзывчивый веб-дизайн не зависит от области просмотра или размера экрана. Дело в размере контейнера. Рассмотрим следующий пример:

Скажите привет контейнерным запросам CSS

У нас очень типичный макет. Имеется два варианта компонентов: вложенный и горизонтальный.

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

.c-article { /* The default, stacked version */
} .c-article > * + * { margin-top: 1rem;
} /* The horizontal version */
@media (min-width: 46rem) { .c-article--horizontal { display: flex; flex-wrap: wrap; } .c-article > * + * { margin-top: 0; } .c-article__thumb { margin-right: 1rem; }
}

Обратите внимание, что мы создали класс .c-article—horizontal для обработки горизонтальной версии компонента. Если ширина области просмотра больше 46 rem, компонент должен переключиться на горизонтальное отображение.

Это неплохо, но существуют некоторые ограниченным. Я хочу, чтобы компонент реагировал на ширину своего родителя, а не на размер окна просмотра или экрана браузера.

Учтите, что мы хотим использовать значение по умолчанию .c-card в основном разделе. Что случится? Что ж, компонент расширится до ширины свого родительского и, следовательно, будет слишком большой. см. следующий рисунок:

Скажите привет контейнерным запросам CSS

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

Скажите привет контейнерным запросам CSS

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

<div class="o-grid"> <div class="o-grid__item"> <article class="c-article"> <!-- content --> </article> </div> <div class="o-grid__item"> <article class="c-article"> <!-- content --> </article> </div>
</div>

.o-grid__item { contain: layout inline-size;
} .c-article { /* The default style */
} @container (min-width: 400px) { .c-article { /* The styles that will make the article horizontal** ** instead of a card style.. */ }
}

Как нам помогут контейнерные запросы CSS?

Предупреждение: контейнерные запросы CSS пока поддерживаются только в Chrome Canary.

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

Вот как я это себе представляю.

Скажите привет контейнерным запросам CSS

Пурпурный контур представляет ширину родительского элемента. Обратите внимание, как при увеличении его размера, компонент адаптируется к этому. Разве это не круто? В этом сила контейнерных запросов CSS.

Как работают контейнерные запросы

Теперь мы можем поэкспериментировать с контейнерными запросами Chrome Сanary. Чтобы включить возможность контейнерных запросов, введите в адресной строке chrome://flags и выполните поиск по запросу «container queries», а затем включите их.

Первый шаг – добавить свойство contain. Поскольку компонент будет адаптироваться в зависимости от его родительской ширины, нам нужно указать браузеру перерисовывать только затронутую область, а не всю страницу. С помощью свойства contain мы можем сообщить об этом браузеру заранее.

Значение inline-size означает реагирование только на изменение ширины родительского элемента. Я пробовал использовать block-size, но он все еще не работает. Пожалуйста, поправьте меня, если я ошибаюсь.

<div class="o-grid"> <div class="o-grid__item"> <article class="c-article"> <!-- content --> </article> </div> <div class="o-grid__item"> <article class="c-article"> <!-- content --> </article> </div> <!-- other articles.. -->
</div>

.o-grid__item { contain: layout inline-size;
}

Это первый шаг. Мы определили элемент .o-grid__item как родительский элемент для .c-article который внутри него. Следующим шагом является добавление стилей, которые мы хотим заставить работать с контейнерными запросами.

.o-grid__item { contain: layout inline-size;
} @container (min-width: 400px) { .c-article { display: flex; flex-wrap: wrap; } /* other CSS.. */
}

@container является элементом .o-grid__item, а его ширина min-width: 400px. Мы даже можем пойти дальше и добавить больше стилей. У нас есть следующие стили:

По умолчанию.

Горизонтальная карточка с маленькой миниатюрой.

Горизонтальная карточка с большой миниатюрой.

Если родительский объект слишком велик, стиль будет указать нам, что это избранная статья.

Давайте рассмотрим варианты использования контейнерных запросов CSS.

Примеры использования контейнерных запросов CSS

Контейнерные запросы и CSS-сетка auto-fit

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

Скажите привет контейнерным запросам CSS

Обратите внимание, что при использовании auto-fit элементы расширяются, чтобы заполнить доступное пространство. Однако в случае auto-fill, элементы сетки не будут расти, и вместо этого у нас будет свободное место (пунктирный элемент справа).

Теперь вы можете спросить, какое отношение это имеет к контейнерным запросам CSS? Что ж, каждый элемент сетки — это контейнер, и когда он расширяется (мы также используем auto-fit), нам нужно, чтобы компонент изменялся в зависимости от контейнера.

<div class="o-grid"> <div class="o-grid__item"> <article class="c-article"></article> </div> <div class="o-grid__item"> <article class="c-article"></article> </div> <div class="o-grid__item"> <article class="c-article"></article> </div> <div class="o-grid__item"> <article class="c-article"></article> </div>
</div>

.o-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-gap: 1rem;
}

Когда у нас есть четыре элемента, результат должен выглядеть примерно так.

Скажите привет контейнерным запросам CSS

Ситуация изменится, когда количество статей станет меньше, вот что произойдет. Чем меньше у нас предметов, тем они станут шире. Причина в том, что используется auto-fit. Первый выглядит хорошо, но два последних (по 2 в ряду, по 1 в ряду) выглядят не очень хорошо, так как они слишком широкие.

Скажите привет контейнерным запросам CSS

Что, если каждый компонент статьи изменяется в зависимости от ширины его родительского элемента? Таким образом, мы можем извлечь выгоду от использования auto-fit. Вот что нам нужно сделать.

Если ширина элемента сетки больше 400 пикселей, статья должна переключиться на горизонтальный стиль. Вот как мы можем это сделать:

.o-grid__item { contain: layout inline-size;
} @container (min-width: 400px) { .c-article { display: flex; flex-wrap: wrap; }
}

Кроме того, если статья является единственным элементом в сетке:

.o-grid__item { contain: layout inline-size;
} @container (min-width: 700px) { .c-article { display: flex; justify-content: center; align-items: center; min-height: 350px; } .card__thumb { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; }
}

Скажите привет контейнерным запросам CSS

Вот и все. У нас есть компонент, который реагирует на ширину своего родителя, и он может работать в любом контексте. Разве это не круто? Посмотрите демонстрацию на CodePen.

Боковая и главная панели

Часто нам нужно настроить компонент, чтобы он работал в контейнерах небольшой ширины, таких как <aside>. Для этого идеально подходит вид информационных бюллетеней. Когда ширина мала, нам нужно, чтобы его элементы складывались в стопку, а когда достаточно места, нам нужно, чтобы они разложились по горизонтали.

Скажите привет контейнерным запросам CSS

Как вы видите на рисунке, у нас есть информационный бюллетень, который существует в двух разных контекстах: боковой раздел и основной раздел.

Без контейнерных запросов это невозможно, пока у нас не будет класса вариаций в CSS, например, .newsletter—stacked или что-то в этом роде.

Я знаю, что мы можем принудительно обернуть элементы, если во флексбоксе недостаточно места, но этого недостаточно. Мне нужно гораздо больше контроля, чтобы делать такие вещи, как:

Скрыть определенные элементы.

Сделать кнопку полной ширины.

.newsletter-wrapper { contain: layout inline-size;
} /* The default, stacked version */
.newsletter { /* CSS styles */
} .newsletter__title { font-size: 1rem;
} .newsletter__desc { display: none;
} /* The horizontal version */
@container (min-width: 600px) { .newsletter { display: flex; justify-content: space-between; align-items: center; } .newsletter__title { font-size: 1.5rem; } .newsletter__desc { display: block; }
}

Посмотрите демонстрацию на CodePen.

Пагинация

Я обнаружил, что разбиение на страницы хорошо подходит для использования контейнерных запросов. Изначально у нас могут быть кнопки «Назад» и «Далее», затем мы можем скрыть их и показать полную разбивку на страницы, если есть достаточно места. Рассмотрим следующий рисунок.

Скажите привет контейнерным запросам CSS

Чтобы обработать состояния, указанные выше, нам нужно сначала поработать со стилем по умолчанию (сложенные кнопки), а затем работать с двумя другими состояниями.

.wrapper { contain: layout inline-size;
} @container (min-width: 250px) { .pagination { display: flex; flex-wrap: wrap; gap: 0.5rem; } .pagination li:not(:last-child) { margin-bottom: 0; }
} @container (min-width: 500px) { .pagination { justify-content: center; } .pagination__item:not(.btn) { display: block; } .pagination__item.btn { display: none; }
}

Посмотрите демонстрацию на CodePen.

Карточка профиля

Скажите привет контейнерным запросам CSS

Вот еще один вариант, который идеально подходит для использования в нескольких контекстах. Маленькое состояние работает для небольших размеров области просмотра и контекстов, таких как боковая панель. Большое состояние работает в гораздо более широком контексте, например, при размещении ее в сетке с двумя столбцами.

.p-card-wrapper { contain: layout inline-size;
} .p-card { /* Default styles */
} @container (min-width: 450px) { .meta { display: flex; justify-content: center; gap: 2rem; border-top: 1px solid #e8e8e8; background-color: #f9f9f9; padding: 1.5rem 1rem; margin: 1rem -1rem -1rem; } /* and other styles */
}

При этом мы можем увидеть компоненты в разных контекстах без использования единого медиа-запроса.

Скажите привет контейнерным запросам CSS

Посмотрите демонстрацию на CodePen.

Элементы формы

Я еще не углублялся в варианты использования форм, но задумал переключиться с горизонтальных меток на штабелированные.

Скажите привет контейнерным запросам CSS

.form-item { contain: layout inline-size;
} .input-group { @container (min-width: 350px) { display: flex; align-items: center; gap: 1.5rem; input { flex: 1; } }
}

Попробуйте сами в демонстрации ниже. Посмотрите демонстрацию на CodePen.

Компоненты тестирования

Теперь, когда мы изучили пару примеров использования, в которых контейнерные запросы CSS могут быть полезны, как мы можем протестировать компонент? К счастью, мы можем сделать это с помощью свойства CSS resize в родительском компоненте.

Скажите привет контейнерным запросам CSS

.parent { contain: layout inline-size; resize: horizontal; overflow: auto;
}

Отладка контейнерных запросов в DevTools

Пока что вы не можете увидеть что-то вроде @container (min-width: value). Думаю, это вопрос времени, и это будет реализовано.

Заключение

Мне понравилось изучать контейнерные запросы CSS и экспериментировать с ними в браузере. Я знаю, что они еще официально не поддерживаются, но сейчас самое время начать работать с ними.

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

Автор: Ahmad Shadeed

Источник: ishadeed.com

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

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