В веб-дизайны сетки, как в Pinterest уже давно не являются чем-то новым. Но что, если нужно сделать блоки различной высоты, при этом чтобы верстка была резиновой. Оказывается, это можно сделать, используя только стандартные возможности CSS Grid Layout.
Рассмотрим пример реализации на CodePen. Мы видим 5 блоков с ассиметричным расположением. Блоки 2, 3 и 4 имеют одинаковую высоту, в то время как блоки 1 и 5 имеют отличные от остальных блоков высоты. При изменении ширины окна браузера блоки уменьшаются в ширину, и в какой-то момент переходят в одну колонку. В блоке 4 находится текст, который при изменении ширины блока растягивает блоки 3 и 4 по высоте, сохраняя при этом структуру сетки.
▎Как это работает
CSS Grid — это способ разделить контейнер на строки и столбцы. Для создания асимметричной структуры нужно указать, сколько строк должен занимать каждый блок. Для этого понадобятся следующие свойства:
grid-gap
Это свойство задает размер промежутков между блоками по обеим осям.
grid-auto-rows
Это свойство задает высоту строки в контейнере. Значение для этого свойства можно указывать в разных единицах измерения. Но чтобы гарантировать, что текст не будет выходить за пределы блоков, нужно указать auto в качестве значения (значение по умолчанию).
В этом случае размер строк определяется наибольшим максимальным размером содержимого в дорожке.
Важно отметить, что промежутки между строками являются частью строк и влияют на высоту блоков.
grid-row-end
Это свойство определяет сколько строк занимает элемент, или на какой строке элемент заканчивается в сетке.
Мы используем это свойство со значение span n, где n это количество строк, которое должен охватывать блок.
В нашем примере высота строки (grid-auto-rows: auto), это значит, что фактически она равна нулю и увеличивается только тогда, когда содержимое будет растягивать блок. Однако, поскольку задан grid-gap, именно это значение будет влиять на расчет высоты блоков.
Если по макету высота блока 150px, а размер промежутков 10px, то количество строк рассчитывается следующим образом: 150 / 10 + 1 = 16. Поэтому в нашем примере для первого блока задано grid-row-end: span 16. Для остальных блоков количеств строк рассчитывается аналогично.
▎Горизонтальное позиционирование
grid-template-columns
Это свойство отвечает за размеры и расположение колонок в контейнере.
Мы используем значение repeat(), позволяющее повторять набор правил для столбцов.
Указав максимальное количество колонок 2 и минимальную ширину колонки 200px, мы обеспечиваем горизонтальную эластичность сетки.
Подробное о реализации автоматического заполнения, можно прочитать в этой статье:
https://css-tricks.com/an-auto-filling-css-grid-with-max-columns/
▎Итого
Если высота блоков в макете кратна значению промежутка (grid-gap), легко совместить точную верстку (Pixel Perfect) с резиновой.
Для автоматического растягивания блоков по высоте используйте grid-auto-rows: auto. Высоту блоков можно задать, указав количество занимаемых строк, вычисляемое по формуле: Высота блока в макете / Значение промежутка + 1.
Для обеспечения эластичности по горизонтали достаточно указать максимальное количество колонок и минимальную ширину колонки, после которой блоки будут переходить на новую строку.
Комментарии (4)
Ntano
05.01.2025 09:34А что делаем если блоки динамикой с сервера валятся?)
kossyak Автор
05.01.2025 09:34Можно определить вариации размерности блоков, вряд ли их будет больше 5. И для каждого из вариантов задать свои значение занимаемых строк. Например grid-row-end: span 5; grid-row-end: span 10; grid-row-end: span 15; И со стороны бэкенда для каждой карточки передавать вариант размера блока, можно его рассчитывать от количества символов в тексте, если это картинки, то от высоты изображения. В любом случает нужно писать дополнительный код. Сетка подразумевает, что между размерами блоков есть связь (пропорции), если ее нет, то только js в помощь.
itBestRay
Классный пример, он наглядно показывает, что для Pinterest-подобных сеток совсем не обязательно вручную высчитывать магические отступы. Единственный момент: если динамически меняется содержимое (например, тексты длиннее), надо внимательно следить за grid-gap, чтобы высота не стала неожиданно “съезжать”
kossyak Автор
На мой взгляд, то что содержимое может немного растянуть блоки это не критично. Но это можно решить, изначально сделав в дизайне макета высоту блоков чуть больше. Я видел такой пример, где на десктопной версии под тестом остается пространство. На крайний случай, можно использовать медиа запросы, немного увеличивая высоту строки grid-auto-rows: 2px; Таким образом мы увеличиваем высоту всех блоков, но сохраняем их пропорции относительно друг-друга.