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