Отзывчивые CSS макеты без медиа-запросов
Основой для многих сайтов по-прежнему остаётся макетная сетка, независимо от того, состоит ли она из Grid или Flexbox. В этом отрывке из книги Unleashing the Power of CSS: Advanced Techniques for Responsive User Interfaces
мы увидим, как оба этих инструмента позволяют создавать плавно реагирующие макетные сетки без медиа-запросов.
Отзывчивый макет с Grid
Первое, пожалуй, моё любимое из всех решений из-за его универсальности и простоты использования. Используя Grid, мы можем создать отзывчивый набор столбцов, которые создают сами себя по мере необходимости. Мы предоставим единственное ограничение — минимальную ширину, которой могут быть столбцы, — выполняющую двойную функцию в качестве своего рода точки останова
перед тем, как элементы столбца разбиваются на новые строки.
Вот всё, что нужно для создания адаптивной макетной сетки, где минимальный размер столба установлен на 30ch
с помощью вспомогательного CSS переменной. Это правило предписывает браузеру создавать как можно больше столбцов шириной не менее 30ch
:
.grid {
--min: 30ch;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--min)), 1fr));
}
Поскольку 1fr
является максимальным
значением функции minmax()
, столбцам также разрешено растягиваться, чтобы равномерно заполнить всё оставшееся пространство в строке. Таким образом, если доступное пространство составляет 80ch
и есть два дочерних элемента Grid, каждый из них займёт по 40ch
. Если дочерних элемента три, третий будет во втором ряду, так как 80ch
не делиться поровну на минимально разрешённый размер 30ch
Следующая демонстрация на CodePen представляет собой живой пример отзывчивого макета Grid.
Отзывчивый макет с Flexbox
Мы можем добиться аналогичного поведения от Flexbox. Разница между решениями Flexbox и Grid заключается в том, что элементы сетки, переходящие в новую строку, не могут распространяться на несколько столбцов сетки. С помощью Flexbox мы можем направить flex-элементы на увеличение, чтобы заполнить всё оставшееся дополнительное пространство, предотвращая сироту
, которая появляется с решением Grid.
В этом коде, как в Grid коде, браузер создаст столько столбцов, сколько уместиться во внутреннем пространстве, по крайней мере с --min
размером 30ch
. Если у нас есть три элемента, а третий нужно переместить на новую строку, он займёт оставшееся место из-за сокращения flex, которое важно устанавливать flex-grow
в 1
. Поэтому в большинстве случаев он ведёт себя аналогично 1fr
:
.flexbox-grid {
--min: 30ch;
display: flex;
flex-wrap: wrap;
}
.flexbox-grid > * {
flex: 1 1 var(--min);
}
На изображении внизу показан последний элемент списка с нечётным номером, занимающий два столбца благодаря свойству flex-grow
.
Примечание: в решениях Grid и Flexbox, если мы добавим gap
это пространство будет вычтено из расчёта того, столько столбцов может быть создано до добавления новых строк.
Внимательные читатели могли заметить ещё одно ключевое различие между этими решениями: при использовании Grid родитель определяет поведение дочернего элемента. Для Flexbox мы устанавливаем дочернее поведение макета для дочерних элементов. Сокращение flex
задаёт по порядку flex-grow
, flex-shrink
и flex-basis
.
В качестве эксперимента мы можем изменить значение flex-grow
на 0
и посмотреть, как элементы будут расширяться только до значения flex-basis
. (Поэкспериментируйте с демонстрацией CodePen ниже.) Важно сохранить flex-shrink
равным 1
, чтобы в конечном итоге — когда доступное внутреннее пространство уже, чем flex-basis
— элементы по-прежнему могли сжиматься
, поскольку оно помогает предотвратить переполнение.
Следующая демонстрация CodePen показывает макет FlexBox в действии.
Свойство flex-basis
можно дополнительно настроить для этого решения, чтобы назначить уникальные точки останова
для разных элементов. Поскольку мы устанавливаем это значение с помощью CSS переменной --min
, а дочерние элементы Flexbox сами контролируют свой размер, мы можем настроить его с помощью встроенного стиля:
<li style="--min: 40ch">...</li>
Другие дочерние элементы списка в этом примере по-прежнему будут окружать его и использовать 30ch
из базового правила, но более широкий столбец эффективно меняет поведение.
Вот CodePen демонстрация этого кода в действии.
Вот ещё две техники Flexbox, которые интересным образом используют flex-grow
и flex-basis
:
- Heydon Pickering’s Flexbox Holy Albatross, который разбивается на столбцы в одну строку в зависимости от общей ширины родительского контейнера.
- Heydon Pickering’s and Andy Bell’s sidebar layout показывающий, как принудительно устанавливать различные точки останова на основе Flexbox для лучшего контроля переноса элементов.