Контейнерные запросы произвели революцию в подходе разработчиков к адаптивному дизайну, и команда Netflix на собственном опыте убедилась в том, какое глубокое влияние они могут оказать на оптимизацию разработки, повышение гибкости и производительности. В этом посте рассматриваются ключевые преимущества использования контейнерных запросов, сравнивая их со старыми методами, особенно с теми, которые используют JavaScript для управления макетом. Он включает примеры кода, иллюстрирующие каждый пункт и показывающие, как контейнерные запросы могут значительно облегчить вашу жизнь как разработчика.
1. Упрощенное проектирование компонентов «снизу вверх» и «сверху вниз».
Одним из наиболее значительных изменений, с которыми столкнулась команда Netflix, стал переход от подхода к проектированию «сверху вниз» к подходу «снизу вверх». Перед запросами к контейнерам родительские контейнеры должны были полностью знать требования к макету своих дочерних элементов. При использовании контейнерных запросов эта логика меняется на противоположную, что позволяет дочерним компонентам управлять своим макетом в зависимости от размера их собственного контейнера. Это упрощает роль родительского элемента и уменьшает объем логики макета в коде.
Пример: контейнерные запросы в сравнении с медиа-запросами и JavaScript.
До (необходим JavaScript):
/* Layout with media queries */
.card {
width: 100%;
}
@media (min-width: 600px) {
.card {
width: 50%;
}
}
@media (min-width: 900px) {
.card {
width: 33.33%;
}
}
// JavaScript to detect parent container size
const container = document.querySelector('.container');
const card = document.querySelector('.card');
function adjustLayout() {
if (window.innerWidth >= 900) {
card.style.width = '33.33%';
} else if (window.innerWidth >= 600) {
card.style.width = '50%';
} else {
card.style.width = '100%';
}
}
window.addEventListener('resize', adjustLayout);
adjustLayout();
После:
/* Container Query */
.container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
В этом примере показано, как родительскому контейнеру больше не нужно управлять дочерним макетом. Правило @container
позволяет .card
реагировать на непосредственный размер контейнера, упрощая логику макета и полностью устраняя необходимость в JavaScript.
2. Отзывчивость без сложных медиазапросов
Команда Netflix обнаружила, как контейнерные запросы упрощают реагирование, особенно при проектировании, ориентированном на мобильные устройства. Вместо написания сложных медиа-запросов вы можете создавать повторно используемые компоненты, которые настраиваются в зависимости от размера их контейнера, что позволяет создавать динамические макеты для экранов различных размеров и устройств. Это особенно полезно для таких приложений, как Netflix, где доминирует мобильный трафик.
Пример. Отзыв компонента на запросы контейнера.
До:
/* Desktop versus Mobile
this only works if.sidebar is directly contained by a viewport-width element */
.sidebar {
width: 300px;
}
@media (max-width: 768px) {
.sidebar {
width: 100%;
}
}
После:
/* Responsive sidebar based on container,
.sidebar can be placed in any element of any width */
.container {
container-type: inline-size;
}
.sidebar {
width: 100%;
}
@container (min-width: 768px) {
.sidebar {
width: 300px;
}
}
Вместо того, чтобы зависеть от медиа-запросов на основе области просмотра, .sidebar
теперь реагирует на размер контейнера, что позволяет ей более естественно адаптироваться к динамическим макетам без необходимости знать размер области просмотра или родительского контейнера.
3. Уменьшена зависимость от JavaScript для управления макетом.
До появления запросов к контейнерам многим командам, включая Netflix, приходилось полагаться на JavaScript для создания динамических макетов. Запрашивая размер окна, JavaScript инициирует изменения макета, увеличивая как сложность, так и вероятность ошибок. Контейнерные запросы устраняют эту необходимость, позволяя CSS обрабатывать реагирование макета в зависимости от размера контейнера.
Пример. Удаление логики макета на основе JavaScript.
До:
const cardContainer = document.querySelector('.card-container');
const cards = cardContainer.children;
function adjustLayout() {
if (cardContainer.offsetWidth > 900) {
cards.forEach(card => card.style.width = '33.33%');
} else if (cardContainer.offsetWidth > 600) {
cards.forEach(card => card.style.width = '50%');
} else {
cards.forEach(card => card.style.width = '100%');
}
}
window.addEventListener('resize', adjustLayout);
adjustLayout();
После:
.card-container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
Этот подход не только уменьшает объем необходимого JavaScript, но и повышает производительность за счет исключения вычислений во время выполнения.
4. Меньше кода, меньше ошибок
Команда Netflix обнаружила, что использование контейнерных запросов приводит к уменьшению количества строк кода и ошибок, связанных с макетом. Перемещая логику макета из JavaScript в CSS и устраняя необходимость в сложных медиа-запросах, разработчики могут писать более удобный в сопровождении код.
Пример: сокращение кода макета
Команда Netflix заметила, что после внедрения контейнерных запросов они заметили значительное сокращение кода CSS — до 30 % для некоторых компонентов. В то же время команде удалось упростить многие сложные и иногда конфликтные медиа-запросы, исключив логику, которая управляла дочерними компонентами, добившись более высокой степени разделения задач. Такое сокращение не только ускоряет разработку, но и сводит к минимуму потенциальные точки сбоя, что приводит к меньшему количеству ошибок.
До:
/* Before with complex media queries */
.card {
width: 100%;
}
@media (min-width: 600px) {
.card {
width: 50%;
}
}
@media (min-width: 900px) {
.card {
width: 33.33%;
}
}
После
.container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
5. Улучшенный опыт разработчика.
бк. «это сделало мою жизнь в сто раз проще»
Возможно, одним из наиболее недооцененных преимуществ контейнерных запросов является улучшение условий для разработчиков. Сделав CSS более интуитивным и ориентированным на компоненты, разработчики могут сосредоточиться на создании многоразовых, гибких компонентов, не беспокоясь о том, как они будут вести себя в каждом возможном сценарии компоновки.
Как сказал один из членов команды Netflix: «Вот как CSS должен был работать с самого начала».
6. Резервный вариант Polyfill
Хотя контейнерные запросы сейчас используются во всех основных браузерах, существуют опасения, что более ранние версии браузеров все еще используются. Резервный вариант очень важен: команда Netflix использует этот полифил JavaScript, созданный участниками веб-сообщества. Реализация проста с обнаружением функций:
if (! CSS.supports("container-type:size")) {
/*use polyfill from
https://www.npmjs.com/package/container-query-polyfill */
}
Заключение
Контейнерные запросы представляют собой огромный шаг вперед в CSS, упрощая разработчикам создание гибких, адаптивных компонентов, которые можно повторно использовать в разных частях сайта. Уменьшая зависимость от JavaScript для макетирования, устраняя сложные медиа-запросы и ускоряя разработку, они предлагают значительные преимущества как в производительности, так и в удобстве сопровождения. В настоящее время большинство вариантов использования находятся на страницах Netflix Tudum , и есть потенциальные планы по использованию контейнерных запросов в других частях Netflix. Команда Netflix считает контейнерные запросы первоклассным инструментом в наборе инструментов разработчика, и их использование будет только расширяться по мере того, как все больше разработчиков осознают гибкость и мощь, которые они приносят. Будь то модернизация существующих компонентов или разработка совершенно новых, контейнерные запросы предлагают более простой и понятный путь к адаптивному дизайну.
Если вы еще этого не сделали, попробуйте контейнерные запросы — вы, скорее всего, обнаружите, что это упрощает ваш рабочий процесс так, как вы не ожидали.