Grid: раскладка страниц по-взрослому

Grid: раскладка страниц по-взрослому

Grid - это двумерная система раскладки. Flexbox работает в одном направлении (строка или колонка), Grid - в обоих одновременно.

Когда Grid, когда Flexbox

Flexbox - для одномерных задач: навбар, кнопки в ряд, карточки в строку. Grid - для двумерных: весь макет страницы (header, sidebar, main, footer), галерея с разноразмерными элементами, dashboard.

Они не конкурируют - дополняют друг друга. Grid для макета, Flexbox внутри ячеек.

Простая сетка

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

1fr - одна фракция (доля) свободного пространства. repeat(3, 1fr) - три равные колонки. Это эквивалент 1fr 1fr 1fr.

/* Разные размеры колонок */
.layout {
  display: grid;
  grid-template-columns: 250px 1fr 200px;
  gap: 24px;
}

Здесь первая колонка 250px (sidebar), вторая - весь остаток (content), третья 200px (aside).

grid-template-rows - строки

.page {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 64px 1fr 80px;
  min-height: 100vh;
}

Три строки: header (64px), main (всё свободное), footer (80px).

Именованные области (grid-template-areas)

Самый наглядный способ описать макет:

.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 64px 1fr 80px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

Каждая строка в кавычках - одна строка сетки. Одинаковые имена означают, что элемент занимает несколько ячеек.

Grid template areas: header растянут на 2 колонки, sidebar + main, footer внизу

Области делают макет «визуальным» прямо в CSS. Ты буквально рисуешь сетку текстом. При изменении макета для мобильных - просто перерисовываешь области в media query.

Позиционирование элементов

grid-column и grid-row

.card--wide {
  grid-column: span 2; /* занимает 2 колонки */
}

.card--tall {
  grid-row: span 2; /* занимает 2 строки */
}

.card--featured {
  grid-column: 1 / 3; /* от линии 1 до линии 3 */
  grid-row: 1 / 2;
}

Линии нумеруются с 1. Сетка из 3 колонок имеет 4 линии (по краям + между колонками).

Линия:  1      2      3      4
        |  1fr  |  1fr  |  1fr  |

Отрицательные номера линий

.full-width {
  grid-column: 1 / -1; /* от первой до последней линии */
}

-1 - последняя линия. Полезно для элементов на всю ширину.

Единица fr - фракция

fr распределяет свободное место пропорционально:

.layout {
  grid-template-columns: 1fr 2fr 1fr;
  /* 25% - 50% - 25% от свободного места */
}

fr учитывает только свободное пространство после фиксированных размеров:

.layout {
  grid-template-columns: 200px 1fr 1fr;
  /* 200px фиксировано, остаток делится пополам */
}

minmax() - гибкие размеры

.grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(200px, 1fr));
  gap: 16px;
}

Каждая колонка минимум 200px, максимум - равная доля. Если не помещается - элементы не сужаются меньше 200px.

auto-fit и auto-fill - адаптивная сетка без media queries

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

Браузер сам определяет, сколько колонок поместится. На 1200px - 4 карточки, на 600px - 2, на телефоне - 1. Без единого media query.

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

gap - промежутки

.grid {
  display: grid;
  gap: 24px;           /* одинаковый gap везде */
  row-gap: 32px;       /* вертикальный */
  column-gap: 16px;    /* горизонтальный */
}

gap работает и в Grid, и в Flexbox. Не нужно возиться с margin.

Выравнивание в Grid

.grid {
  /* Выравнивание всей сетки внутри контейнера */
  justify-content: center;  /* горизонтально */
  align-content: center;    /* вертикально */

  /* Выравнивание элементов внутри ячеек */
  justify-items: center;    /* горизонтально */
  align-items: center;      /* вертикально */
}

/* Для конкретного элемента */
.special {
  justify-self: end;
  align-self: start;
}

Практические паттерны

Макет страницы (Holy Grail Layout)

.page {
  display: grid;
  grid-template-areas:
    "header header header"
    "nav    main   aside"
    "footer footer footer";
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

Bento Grid (карточки разных размеров)

.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 200px);
  gap: 16px;
}

.bento__hero {
  grid-column: span 2;
  grid-row: span 2;
}

.bento__wide {
  grid-column: span 2;
}

Адаптивная галерея

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
}
Для навбара, кнопок в ряд, центрирования одного элемента - Flexbox проще. Grid - когда нужна двумерная сетка или макет страницы.

Мини-задание

  • Сделай сетку 3 колонки с repeat(3, 1fr) и gap: 16px
  • Сделай одну карточку широкой (grid-column: span 2)
  • Создай макет страницы с grid-template-areas (header, sidebar, main, footer)
  • Сделай адаптивную галерею с auto-fit и minmax()
  • Поэкспериментируй с fr - сделай колонки 1fr 2fr 1fr

Зарегистрируйтесь бесплатно, чтобы пройти квиз, решить задание с автопроверкой и вести прогресс.