Модуль 5: Flexbox и CSS Grid
Два мощнейших инструмента CSS для создания любых макетов — от простых до самых сложных.
Часть 1: Flexbox
Введение в Flexbox
Flexbox (Flexible Box Layout) — модуль CSS для создания одномерных макетов. Идеален для выравнивания элементов в ряд или колонку.
Ключевые концепции
- Flex Container — родительский элемент с
display: flex - Flex Items — прямые дочерние элементы контейнера
- Main Axis — главная ось (по умолчанию горизонтальная)
- Cross Axis — поперечная ось (перпендикулярная главной)
/* Активация Flexbox */
.container {
display: flex; /* или inline-flex для инлайнового контейнера */
}
/* Все прямые дочерние элементы становятся flex items */
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
Свойства Flex Container
flex-direction
Определяет направление главной оси:
.container {
display: flex;
/* Значения flex-direction */
flex-direction: row; /* → слева направо (по умолчанию) */
flex-direction: row-reverse; /* ← справа налево */
flex-direction: column; /* ↓ сверху вниз */
flex-direction: column-reverse; /* ↑ снизу вверх */
}
flex-wrap
Управляет переносом элементов:
.container {
flex-wrap: nowrap; /* Все в одну линию (по умолчанию) */
flex-wrap: wrap; /* Перенос на новую строку */
flex-wrap: wrap-reverse; /* Перенос в обратном направлении */
}
/* Сокращённая запись */
.container {
flex-flow: row wrap; /* flex-direction + flex-wrap */
}
justify-content
Выравнивание по главной оси:
.container {
justify-content: flex-start; /* В начало (по умолчанию) */
justify-content: flex-end; /* В конец */
justify-content: center; /* По центру */
justify-content: space-between; /* Равные промежутки между */
justify-content: space-around; /* Равные промежутки вокруг */
justify-content: space-evenly; /* Абсолютно равные промежутки */
}
align-items
Выравнивание по поперечной оси:
.container {
align-items: stretch; /* Растянуть (по умолчанию) */
align-items: flex-start; /* В начало */
align-items: flex-end; /* В конец */
align-items: center; /* По центру */
align-items: baseline; /* По базовой линии текста */
}
align-content
Выравнивание строк при flex-wrap: wrap:
.container {
flex-wrap: wrap;
align-content: flex-start; /* Строки в начало */
align-content: flex-end; /* Строки в конец */
align-content: center; /* Строки по центру */
align-content: space-between; /* Промежутки между строками */
align-content: space-around; /* Промежутки вокруг строк */
align-content: stretch; /* Растянуть строки */
}
gap
Отступы между элементами (современный способ):
.container {
display: flex;
gap: 1rem; /* Одинаковый gap */
gap: 1rem 2rem; /* row-gap column-gap */
/* Отдельные свойства */
row-gap: 1rem;
column-gap: 2rem;
}
Совет
Используйте gap вместо margin на flex items — это чище и не создаёт лишних отступов по краям.
Свойства Flex Items
flex-grow
Как элемент будет расти относительно других:
.item {
flex-grow: 0; /* Не расти (по умолчанию) */
flex-grow: 1; /* Занять доступное пространство */
flex-grow: 2; /* Расти в 2 раза больше чем flex-grow: 1 */
}
/* Пример: sidebar фиксированный, main растягивается */
.sidebar { flex-grow: 0; width: 300px; }
.main { flex-grow: 1; }
flex-shrink
Как элемент будет сжиматься:
.item {
flex-shrink: 1; /* Сжиматься пропорционально (по умолчанию) */
flex-shrink: 0; /* Не сжиматься */
flex-shrink: 2; /* Сжиматься в 2 раза сильнее */
}
/* Пример: изображение не сжимается */
.image { flex-shrink: 0; }
.text { flex-shrink: 1; }
flex-basis
Начальный размер элемента до распределения пространства:
.item {
flex-basis: auto; /* Размер на основе контента (по умолчанию) */
flex-basis: 0; /* Игнорировать размер контента */
flex-basis: 200px; /* Фиксированный начальный размер */
flex-basis: 25%; /* Процент от контейнера */
}
flex (сокращение)
Объединяет grow, shrink и basis:
.item {
/* flex: grow shrink basis */
flex: 0 1 auto; /* По умолчанию */
flex: 1; /* = flex: 1 1 0 (расти, сжиматься, без начального размера) */
flex: auto; /* = flex: 1 1 auto */
flex: none; /* = flex: 0 0 auto (не изменяться) */
flex: 0 0 200px; /* Фиксированный размер 200px */
}
/* Колонки одинаковой ширины */
.column {
flex: 1;
}
/* 2 колонки + sidebar */
.main { flex: 2; } /* 2/3 */
.sidebar { flex: 1; } /* 1/3 */
align-self
Переопределение align-items для конкретного элемента:
.container {
align-items: flex-start;
}
.special-item {
align-self: center; /* Только этот элемент по центру */
align-self: flex-end; /* В конец */
align-self: stretch; /* Растянуть */
}
order
Изменение визуального порядка:
.item { order: 0; } /* По умолчанию */
.item:first-child { order: 3; } /* Переместить в конец */
.item:last-child { order: -1; } /* Переместить в начало */
/* Полезно для изменения порядка на мобильных */
@media (max-width: 768px) {
.sidebar { order: 2; } /* Sidebar после контента */
.main { order: 1; }
}
Осторожно с order
Изменение визуального порядка не меняет порядок в DOM. Это может запутать пользователей скринридеров и тех, кто использует Tab для навигации.
Паттерны Flexbox
1. Центрирование (Holy Grail)
/* Идеальное центрирование */
.center {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
2. Навигация с логотипом
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.nav-links {
display: flex;
gap: 2rem;
}
3. Карточка с footer внизу
.card {
display: flex;
flex-direction: column;
height: 100%;
}
.card-content {
flex: 1; /* Растягивается */
}
.card-footer {
margin-top: auto; /* Прижат к низу */
}
4. Равные колонки
.columns {
display: flex;
gap: 2rem;
}
.column {
flex: 1; /* Все одинаковой ширины */
}
/* Или с минимальной шириной и переносом */
.columns {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.column {
flex: 1 1 300px; /* Минимум 300px, растёт равномерно */
}
5. Media Object
.media {
display: flex;
gap: 1rem;
}
.media-image {
flex-shrink: 0;
width: 80px;
height: 80px;
}
.media-content {
flex: 1;
}
6. Input с кнопкой
.input-group {
display: flex;
}
.input-group input {
flex: 1;
border-radius: 8px 0 0 8px;
}
.input-group button {
flex-shrink: 0;
border-radius: 0 8px 8px 0;
}
Практика
Создайте горизонтальную навигацию, где логотип слева, ссылки по центру, и кнопки (Login/Sign Up) справа.
Часть 2: CSS Grid
Введение в CSS Grid
CSS Grid — мощная система для создания двумерных макетов. Позволяет управлять строками и колонками одновременно.
Терминология Grid
- Grid Container — элемент с
display: grid - Grid Item — прямой дочерний элемент
- Grid Line — линии, разделяющие ячейки
- Grid Track — строка или колонка
- Grid Cell — одна ячейка
- Grid Area — прямоугольная область из нескольких ячеек
/* Активация Grid */
.container {
display: grid; /* или inline-grid */
}
Свойства Grid Container
grid-template-columns / grid-template-rows
.grid {
display: grid;
/* Фиксированные размеры */
grid-template-columns: 200px 200px 200px;
/* Функция repeat() */
grid-template-columns: repeat(3, 200px);
/* Фракции (fr) — пропорциональные части */
grid-template-columns: 1fr 1fr 1fr; /* 3 равные колонки */
grid-template-columns: 1fr 2fr 1fr; /* Средняя в 2 раза шире */
grid-template-columns: 200px 1fr 200px; /* Фиксированные края */
/* minmax() */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* auto-fill / auto-fit */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
auto-fill vs auto-fit
- auto-fill — создаёт столько колонок, сколько помещается (могут быть пустые)
- auto-fit — то же, но пустые колонки схлопываются (элементы растягиваются)
gap
.grid {
gap: 1rem; /* Одинаковый gap */
gap: 1rem 2rem; /* row-gap column-gap */
row-gap: 1rem;
column-gap: 2rem;
}
justify-items / align-items
.grid {
/* Выравнивание элементов внутри ячеек */
justify-items: stretch; /* По горизонтали (по умолчанию) */
align-items: stretch; /* По вертикали (по умолчанию) */
/* Другие значения: start, end, center */
place-items: center; /* Сокращение: align-items justify-items */
}
justify-content / align-content
.grid {
/* Выравнивание всей сетки внутри контейнера */
justify-content: center; /* Горизонтально */
align-content: center; /* Вертикально */
/* Значения: start, end, center, space-between, space-around, space-evenly */
place-content: center; /* Сокращение */
}
grid-auto-rows / grid-auto-columns
.grid {
grid-template-columns: repeat(3, 1fr);
/* Высота автоматически созданных строк */
grid-auto-rows: 200px;
grid-auto-rows: minmax(100px, auto);
/* Направление автозаполнения */
grid-auto-flow: row; /* По строкам (по умолчанию) */
grid-auto-flow: column; /* По колонкам */
grid-auto-flow: dense; /* Заполнять пустоты */
}
Свойства Grid Items
grid-column / grid-row
.item {
/* Позиционирование по линиям */
grid-column-start: 1;
grid-column-end: 3;
/* Сокращённая запись: start / end */
grid-column: 1 / 3; /* От линии 1 до линии 3 */
grid-column: 1 / span 2; /* От линии 1, занять 2 колонки */
grid-column: span 2; /* Занять 2 колонки (автопозиция) */
grid-column: 1 / -1; /* От начала до конца */
/* То же для строк */
grid-row: 1 / 3;
}
Именованные линии
.grid {
grid-template-columns:
[sidebar-start] 250px
[sidebar-end main-start] 1fr
[main-end];
}
.sidebar {
grid-column: sidebar-start / sidebar-end;
}
.main {
grid-column: main-start / main-end;
}
justify-self / align-self
.item {
justify-self: center; /* Горизонтальное выравнивание */
align-self: end; /* Вертикальное выравнивание */
place-self: center end; /* Сокращение */
}
Grid Areas (Области)
grid-template-areas
Визуальный способ задания макета:
.layout {
display: grid;
grid-template-columns: 250px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
min-height: 100vh;
gap: 1rem;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
Адаптивные Areas
/* Мобильные: всё в одну колонку */
.layout {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"aside"
"footer";
}
/* Планшеты */
@media (min-width: 768px) {
.layout {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
}
/* Десктоп */
@media (min-width: 1024px) {
.layout {
grid-template-columns: 200px 1fr 200px;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
}
}
Пустые ячейки
Используйте точку . для обозначения пустой ячейки:
grid-template-areas:
"header header ."
"sidebar main aside"
". footer .";
Паттерны CSS Grid
1. Auto-fit карточки
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
2. Masonry-подобный layout
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: 10px;
gap: 1rem;
}
.masonry-item {
/* Разная высота через span */
}
.masonry-item.small { grid-row: span 15; }
.masonry-item.medium { grid-row: span 25; }
.masonry-item.large { grid-row: span 35; }
3. Pancake Stack (полная высота)
.page {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
/* header и footer по контенту, main растягивается */
4. Holy Grail Layout
.holy-grail {
display: grid;
grid-template:
"header header header" auto
"nav main aside" 1fr
"footer footer footer" auto
/ 200px 1fr 200px;
min-height: 100vh;
gap: 1rem;
}
5. Центрирование
.center {
display: grid;
place-items: center;
min-height: 100vh;
}
6. RAM (Repeat, Auto, Minmax)
/* Универсальный адаптивный грид */
.ram {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
gap: 1rem;
}
/* min(100%, 300px) предотвращает overflow на узких экранах */
Практика
Создайте галерею изображений с помощью CSS Grid, где карточки автоматически заполняют доступное пространство (минимум 250px на карточку).
Subgrid
Subgrid позволяет дочерним элементам наследовать линии родительского грида. Это решает проблему выравнивания вложенных элементов.
Проблема без subgrid
/* Без subgrid: заголовки карточек не выровнены */
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
display: grid;
/* Собственный грид, не связан с родителем */
}
Решение с subgrid
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Определяем строки для выравнивания */
grid-template-rows: subgrid;
gap: 1rem;
}
.card {
display: grid;
grid-row: span 3; /* Занимает 3 строки */
grid-template-rows: subgrid; /* Наследует строки родителя */
}
Практический пример
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.product-card {
display: grid;
grid-template-rows: auto 1fr auto auto; /* image, title, description, price */
gap: 0.5rem;
}
/* С subgrid все карточки выровнены */
@supports (grid-template-rows: subgrid) {
.product-grid {
grid-template-rows: repeat(4, auto);
}
.product-card {
grid-row: span 4;
grid-template-rows: subgrid;
}
}
Поддержка браузерами
Subgrid поддерживается во всех современных браузерах (Chrome 117+, Firefox 71+, Safari 16+). Используйте @supports для fallback.
Когда использовать Flex vs Grid
| Flexbox | CSS Grid |
|---|---|
| Одномерный — строка или колонка | Двумерный — строки и колонки |
| Контент определяет размер | Сетка определяет размер |
| Гибкое распределение пространства | Точное позиционирование |
| Выравнивание элементов в ряду | Сложные макеты страниц |
Используйте Flexbox для:
- Навигации и меню
- Карточек с контентом разной высоты
- Выравнивания элементов в одном направлении
- Компонентов UI (кнопки, формы)
- Когда размер определяется контентом
Используйте Grid для:
- Макетов страниц (header, sidebar, main, footer)
- Галерей и сеток карточек
- Когда нужно выравнивание по двум осям
- Перекрывающихся элементов
- Когда макет должен быть строгим
Комбинируйте!
/* Grid для общего макета */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
}
/* Flex для навигации внутри header */
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Grid для карточек в main */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
/* Flex для содержимого карточки */
.card {
display: flex;
flex-direction: column;
}
.card-footer {
margin-top: auto;
}
Реальные макеты
1. Dashboard Layout
.dashboard {
display: grid;
grid-template-columns: 280px 1fr;
grid-template-rows: 60px 1fr;
grid-template-areas:
"sidebar header"
"sidebar main";
min-height: 100vh;
}
.sidebar {
grid-area: sidebar;
background: var(--sidebar-bg);
}
.header {
grid-area: header;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 2rem;
}
.main {
grid-area: main;
padding: 2rem;
overflow-y: auto;
}
/* Мобильная версия */
@media (max-width: 1024px) {
.dashboard {
grid-template-columns: 1fr;
grid-template-rows: 60px 1fr;
grid-template-areas:
"header"
"main";
}
.sidebar {
position: fixed;
transform: translateX(-100%);
transition: transform 0.3s;
}
.sidebar.open {
transform: translateX(0);
}
}
2. Blog Layout
.blog {
display: grid;
grid-template-columns:
1fr
min(65ch, 100%)
1fr;
row-gap: 2rem;
}
.blog > * {
grid-column: 2;
}
/* Полноширинные элементы */
.blog .full-width {
grid-column: 1 / -1;
}
/* Элементы шире текста */
.blog .wide {
grid-column: 1 / -1;
width: min(100%, 1200px);
justify-self: center;
}
3. E-commerce Product Grid
.products {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
gap: 1.5rem;
}
.product-card {
display: grid;
grid-template-rows: 200px auto auto 1fr auto;
gap: 0.75rem;
background: var(--card-bg);
border-radius: 12px;
overflow: hidden;
}
.product-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.product-actions {
display: flex;
gap: 0.5rem;
padding: 1rem;
}
.product-actions button {
flex: 1;
}
4. Hero с перекрытием
.hero {
display: grid;
grid-template-rows: 1fr auto 1fr;
min-height: 80vh;
position: relative;
}
.hero::before {
content: '';
grid-row: 1 / -1;
grid-column: 1;
background: linear-gradient(to right, rgba(0,0,0,0.7), transparent);
}
.hero-image {
grid-row: 1 / -1;
grid-column: 1;
width: 100%;
height: 100%;
object-fit: cover;
}
.hero-content {
grid-row: 2;
grid-column: 1;
z-index: 1;
max-width: 600px;
padding: 2rem;
}
Итоговый проект
Создайте полноценный макет интернет-магазина с использованием Grid и Flexbox:
- Header с навигацией (Flex)
- Hero-секция с перекрытием (Grid)
- Сетка товаров (Grid + auto-fit)
- Карточки товаров (Flex column)
- Footer с несколькими колонками (Grid)
- Полностью адаптивный дизайн