Menu

CSS Grid: колонки, строки, fr, gap и области

CSS Grid размещает элементы сразу по строкам и колонкам. Разберем display: grid, grid-template-columns, единицу fr, repeat() и minmax(), auto-fill и auto-fit, размещение элементов через grid-column и grid-template-areas на живой сетке, которую можно менять и измерять.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Сетка в три строки

Задайте контейнеру display: grid и перечислите его колонки в grid-template-columns. Дочерние элементы заполняют ячейки по порядку, слева направо в русском, и новая строка начинается, когда колонки заполнены:

Семь элементов, три колонки: две полные строки и третья с элементом 7 в первой колонке. Все колонки одинаковой ширины, и все элементы в строке одинаковой высоты, поэтому края выровнены в обоих направлениях. Именно это grid добавляет к flexbox.

Песочница grid

Введите любое значение grid-template-columns или кликните по готовому варианту. Ниже показаны ширины колонок, которые вычислил браузер (через getComputedStyle), и сколько строк понадобилось элементам:

На что посмотреть: 1fr 2fr делает вторую колонку ровно вдвое шире первой. 200px 1fr сохраняет 200px и отдает остальное второй колонке. auto 1fr auto задает внешним колонкам ширину по содержимому. repeat(4, 100px) оставляет пустое место в конце, потому что ничего не тянется. Невалидное значение, например 1fr 2, игнорируется, и сетка сохраняет последнее валидное.

Единица fr

fr означает «одна доля свободного пространства». Браузер сначала вычитает фиксированные колонки (px, rem, %, содержимое auto) и промежутки, а затем делит остаток между колонками fr по их числам.

grid-template-columns в контейнере 600px без промежутковШирины колонок
1fr 1fr 1fr200, 200, 200
1fr 2fr200, 400
100px 1fr 1fr100, 250, 250
1fr 50%300, 300

fr это не %: проценты вместе с промежутками могут дать больше 100% и переполнить контейнер, а колонки fr всегда делят только то, что осталось после промежутков.

repeat(), minmax() и адаптивная сетка без медиазапросов

repeat(4, 1fr) это 1fr 1fr 1fr 1fr. minmax(120px, 1fr) это колонка, которая никогда не бывает уже 120px и растет, забирая свою долю. Соедините их с auto-fill или auto-fit вместо числа, и сетка создаст столько колонок, сколько поместится:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

Одно объявление дает столько колонок шириной не меньше 180px, сколько вмещает контейнер: несколько на широком экране, одну на телефоне, без медиазапросов. Разница между auto-fill и auto-fit видна, когда элементов меньше, чем колонок:

В контейнер помещается пять колонок по 100px. auto-fill сохраняет все пять, поэтому A, B и C по 112px, а две пустые колонки остаются. auto-fit схлопывает пустые, и три элемента растягиваются примерно до 187px каждый.

Размещение элементов: grid-column и grid-row

Линии сетки нумеруются с 1 от начального края. grid-column: 1 / 3 значит «от линии 1 до линии 3», то есть две колонки. span 2 значит «две колонки от того места, где элемент окажется», а -1 это последняя линия:

Темный элемент заполняет всю первую строку. Синий занимает блок 2 на 2, янтарный две строки. Элементы a и b сами заполняют оставшиеся ячейки: grid ставит каждый элемент, какой может, в следующую свободную ячейку. grid-auto-rows: 60px задает высоту строк, которые вы не объявили в grid-template-rows.

grid-template-areas: дайте имена частям раскладки

Для раскладки страницы назовите области и нарисуйте их текстом. Каждая строка в кавычках это строка сетки, каждое слово ячейка, а элемент присоединяется к области через grid-area:

Шапка и подвал охватывают обе колонки, потому что их имена заполняют обе ячейки своих строк. Средняя строка 1fr, поэтому она забирает оставшуюся от 280px высоту. Чтобы сложить все в столбик на телефоне, медиазапросу достаточно перерисовать области в одну колонку: grid-template-areas: "header" "side" "main" "footer" с grid-template-columns: 1fr. Этот прием показан на странице про медиазапросы.

Выравнивание внутри ячеек

По умолчанию grid-элементы растягиваются на свою ячейку. Эти свойства двигают их внутри нее:

СвойствоУ когоЧто двигает
justify-itemsконтейнеркаждый элемент вдоль строки (строчная ось)
align-itemsконтейнеркаждый элемент вверх и вниз (блочная ось)
place-itemsконтейнерсокращение: place-items: center центрирует в обоих направлениях
justify-self / align-selfэлементодин элемент
justify-content / align-contentконтейнервесь набор дорожек, когда сетка меньше контейнера

display: grid; place-items: center; это самый короткий способ выровнять один дочерний элемент по центру блока.

Grid или flexbox

Grid двумерный: вы задаете колонки (и строки), а содержимое заполняет их, поэтому все карточки в галерее одинаковой ширины даже в последней строке. Flexbox одномерный: элементы берут размер от содержимого вдоль одной линии. Они хорошо сочетаются: grid для страницы и галереи карточек, flexbox внутри каждой карточки для ее верхней строки. Вторая половина разобрана на странице про Flexbox CSS.

Порядок и доступность

grid-template-areas, grid-row, grid-column и order могут поставить элемент куда угодно, но программы чтения с экрана и клавиша Tab все равно следуют порядку HTML. Сохраняйте осмысленный порядок в коде (шапка, навигация, основное содержимое, подвал) и используйте grid, чтобы его расставить, а не чтобы исправлять бессмысленный порядок HTML.

Частые ошибки

  • display: grid у элементов. Его задают родителю; grid-элементами являются только прямые дочерние элементы.
  • Проценты вместе с промежутками. grid-template-columns: 50% 50% плюс gap: 16px переполняет контейнер на 16px. Используйте 1fr 1fr.
  • auto-fill, когда нужен auto-fit. При малом числе элементов auto-fill оставляет пустые колонки. Переключитесь на auto-fit, чтобы элементы растянулись.
  • Колонка 1fr растет больше своей доли. Колонка 1fr не сжимается уже самого длинного содержимого (длинного URL, широкого изображения). Используйте minmax(0, 1fr), чтобы она могла сжиматься.
  • Области, которые не образуют прямоугольник. Каждая именованная область должна быть прямоугольником, а в каждой строке должно быть одинаковое число ячеек, иначе все объявление grid-template-areas игнорируется.
  • Забыли, что линии нумеруются с 1. У трех колонок четыре линии: 1 / 4 или 1 / -1 охватывает все три.

Часто задаваемые вопросы

Что такое CSS Grid?

Система раскладки, которая размещает элементы по строкам и колонкам одновременно. Вы задаете контейнеру display: grid, описываете его колонки через grid-template-columns (и при желании строки), а прямые дочерние элементы по порядку заполняют ячейки.

Что означает 1fr в CSS Grid?

fr это доля свободного пространства grid-контейнера. grid-template-columns: 1fr 1fr 1fr дает три равные колонки, а 1fr 2fr делает вторую колонку вдвое шире первой. Сначала вычитаются фиксированные размеры и промежутки, а колонки fr делят то, что осталось.

Чем auto-fill отличается от auto-fit?

Оба создают столько колонок, сколько помещается. auto-fill сохраняет пустые колонки, поэтому несколько элементов остаются узкими и оставляют пустое место в конце строки. auto-fit схлопывает пустые колонки, и элементы растягиваются на всю строку. Если элементов достаточно, чтобы заполнить строку, оба выглядят одинаково.

Как растянуть grid-элемент на две колонки?

Задайте элементу grid-column: span 2 или укажите начальную и конечную линии: grid-column: 1 / 3 охватывает колонки 1 и 2. grid-column: 1 / -1 растягивает на всю ширину, потому что -1 это последняя линия.

Когда использовать grid вместо flexbox?

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

grid-gap и gap это одно и то же?

Да. grid-gap, grid-row-gap и grid-column-gap это старые имена. Браузеры все еще принимают их как псевдонимы, но пишите gap, row-gap и column-gap, которые работают и во flexbox.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ