Урок 4.4: Flexbox
Модуль 4 — Основы CSS
display: flex — контейнер становится «умным»
Раньше, чтобы расположить элементы в ряд, разработчики мучились с float, inline-block и магией отрицательных margin'ов. Это было больно. Потом пришёл Flexbox — и всё стало просто.
Flexbox (сокращение от Flexible Box Layout) — это CSS-модуль, который делает раскладку элементов предсказуемой и гибкой. Всё, что нужно — сказать родителю display: flex, и его дети волшебным образом выстраиваются в аккуратный ряд.
.container {
display: flex;
}
Вот и всё. Одна строчка — и дочерние элементы перестают быть просто блоками друг под другом. Они становятся flex-элементами и слушаются своего родителя-контейнера.
Без flex'а каждый <div> был бы на своей строке. С flex'ом они дружно стоят плечом к плечу. Но это только начало. Настоящая сила flexbox раскрывается, когда мы начинаем управлять тем, как именно они стоят.
Flexbox работает в двух измерениях, но по-настоящему он крут в одном — вдоль главной оси (main axis) и поперечной оси (cross axis). Главная ось — это направление, в котором располагаются элементы. По умолчанию — слева направо (как строки в тексте).
Давай посмотрим на схему:
──────── главная ось (main axis) ────────→
┌────────────────────────────────────────┐
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐│
│ │ 1 │ │ 2 │ │ 3 │ │ 4 ││
↑ │ └──────┘ └──────┘ └──────┘ └──────┘│
│ └────────────────────────────────────────┘
поперечная ось (cross axis)
Пока просто запомни: main axis — это куда смотрят элементы (по умолчанию вправо), а cross axis — перпендикулярно им (по умолчанию вниз). Все свойства flexbox крутятся вокруг этих двух осей.
flex-direction — направление
По умолчанию элементы выстраиваются в строку (слева направо). Но flexbox умеет и в колонку. За это отвечает свойство flex-direction.
.container {
display: flex;
flex-direction: row; /* по умолчанию — в строку */
flex-direction: row-reverse; /* строка задом наперёд */
flex-direction: column; /* в колонку сверху вниз */
flex-direction: column-reverse; /* колонка снизу вверх */
}
Вот как выглядит разница между row и column:
flex-direction: row
flex-direction: column
Когда ты меняешь flex-direction, главная ось поворачивается. При row элементы идут вправо (main axis — горизонталь). При column — вниз (main axis — вертикаль). Все остальные свойства flexbox, которые мы будем разбирать, работают относительно этой оси.
row-reverse и column-reverse делают то же самое, но в обратном порядке:
row-reverse
column-reverse
Порядок меняется визуально, HTML остаётся тем же. Это удобно, когда нужно изменить порядок отображения без изменения разметки.
justify-content — выравнивание по главной оси
Это, пожалуй, самое часто используемое свойство flexbox. justify-content управляет тем, как элементы распределяются вдоль главной оси (то есть вправо вдоль строки или вниз вдоль колонки).
.container {
display: flex;
justify-content: flex-start; /* прижаты к началу (по умолчанию) */
justify-content: flex-end; /* прижаты к концу */
justify-content: center; /* по центру */
justify-content: space-between; /* первый в начале, последний в конце, остальные поровну */
justify-content: space-around; /* равные отступы вокруг каждого */
justify-content: space-evenly; /* строго равные отступы */
}
Смотри, как это выглядит на практике. Каждый пример — один и тот же контейнер с разным justify-content:
flex-start
flex-end
center — самый популярный
space-between
space-around
space-evenly
Обрати внимание на разницу между space-between и space-evenly. В space-between первый элемент прижат к левому краю, последний — к правому. В space-evenly отступы между всеми элементами (включая края) строго одинаковые. space-around — компромисс: отступы вокруг каждого элемента одинаковы, но по краям они в два раза меньше (потому что не складываются с соседними).
justify-content: center — самый частый способ отцентрировать группу элементов по горизонтали. Но для центрирования одного элемента всё равно используй его — это проще, чем margin: auto.
align-items — выравнивание по поперечной оси
Если justify-content работает вдоль главной оси, то align-items — вдоль поперечной. Простыми словами: если элементы идут в ряд (row), align-items управляет их положением по вертикали.
.container {
display: flex;
align-items: stretch; /* растянуть на всю высоту (по умолчанию) */
align-items: flex-start; /* прижать к верху */
align-items: flex-end; /* прижать к низу */
align-items: center; /* отцентрировать по вертикали */
align-items: baseline; /* выровнять по базовой линии текста */
}
Посмотри на разницу. Здесь все контейнеры имеют высоту 120px, а элементы — разной высоты:
stretch
center — вертикальный центр
flex-end
Самое частое использование align-items: center — отцентрировать элемент по вертикали. Раньше для этого приходилось танцевать с бубном, а теперь — одна строка CSS.
.parent {
display: flex;
align-items: center; /* по вертикали */
justify-content: center; /* по горизонтали */
}
/* Идеальное центрирование одной строкой! */
Вот как это выглядит:
Всего два свойства — и элемент идеально отцентрирован и по вертикали, и по горизонтали. Внутри блока может быть что угодно: текст, картинка, форма. flexbox всё отцентрирует.
Это настолько распространённый паттерн, что его выделяют в отдельный класс:
.center {
display: flex;
align-items: center;
justify-content: center;
}
Используй его для иконок в кружках, для центрирования модальных окон, для прелоадеров — везде, где нужно что-то разместить ровно посередине.
gap — расстояние между элементами
Раньше, чтобы сделать отступы между flex-элементами, использовали margin на каждом элементе. Это работало, но было муторно — нужно было убрать margin у последнего элемента, чтобы не было лишнего отступа. Потом появился gap, и всё стало проще.
.container {
display: flex;
gap: 20px; /* расстояние между всеми элементами */
}
/* Можно задавать разные значения для строк и колонок */
gap: 16px 24px; /* row-gap column-gap */
row-gap: 16px;
column-gap: 24px;
gap добавляет отступы только между элементами. До и после первого/последнего элемента отступов нет. Это идеально для списков, меню, карточек.
gap: 8px
Обрати внимание: во втором примере отступы между элементами 24px, но до левого и правого края отступа нет. gap не добавляет отступов по краям, только между элементами. Если нужны отступы по краям — используй padding на контейнере.
gap вместо margin на flex-детях. Это чище, короче и не требует костылей для последнего элемента.
flex-wrap — перенос на новую строку
По умолчанию flex-элементы стараются поместиться в одну строку. Если они не влезают, они сжимаются (flexbox умеет уменьшать элементы). Но часто нужно, чтобы они переносились на следующую строку — как слова в тексте. Для этого есть flex-wrap.
.container {
display: flex;
flex-wrap: nowrap; /* не переносить (по умолчанию) */
flex-wrap: wrap; /* переносить, если не влезают */
flex-wrap: wrap-reverse; /* переносить в обратном порядке */
}
Посмотри, как работает wrap:
flex-wrap: nowrap — элементы сжимаются
flex-wrap: wrap — перенос на новую строку
flex-basis: 200px переносятся, когда не влезаютОбрати внимание: когда элементы переносятся, они создают несколько рядов. Каждый ряд работает как отдельный flex-контейнер. Flex-wrap особенно полезен для:
- Сеток карточек (каталог товаров, галерея)
- Тегов и категорий
- Меню, где пункты могут не поместиться
- Списков иконок с подписями
Вот пример сетки карточек с flex-wrap:
Смартфон
49 990 ₽
Ноутбук
89 990 ₽
Наушники
7 490 ₽
Часы
24 990 ₽
Камера
55 000 ₽
Принтер
12 990 ₽
Каждая карточка имеет фиксированную ширину 170px. Когда они не влезают в ряд, flex-wrap переносит их на следующую строку. И gap создаёт аккуратные отступы между ними. Всё это — без единого margin или float.
Практика: карточки товаров в ряд, центрирование блока
Давай соберём всё, что мы выучили, в один проект. Мы сверстаем секцию с товарами:
- Карточки товаров в ряд
- Центрирование содержимого
- Отступы между карточками через gap
- Перенос на новую строку, если не влезают
Вот полный код. Скопируй и открой в браузере:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Каталог товаров</title>
<style>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', system-ui, sans-serif;
background: #f5f5f5;
margin: 0;
padding: 40px 20px;
}
.section-title {
text-align: center;
font-size: 1.8em;
color: #333;
margin-bottom: 32px;
}
.product-grid {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 24px;
max-width: 900px;
margin: 0 auto;
}
.product-card {
background: #fff;
border-radius: 14px;
padding: 24px 20px;
width: 240px;
text-align: center;
box-shadow: 0 2px 12px rgba(0,0,0,0.06);
transition: transform 0.2s, box-shadow 0.2s;
}
.product-card:hover {
transform: translateY(-4px);
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
}
.product-icon {
width: 80px;
height: 80px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2em;
margin: 0 auto 16px;
}
.product-card h3 {
margin: 0 0 6px;
color: #333;
font-size: 1.2em;
}
.product-desc {
color: #777;
font-size: 0.9em;
margin: 0 0 14px;
line-height: 1.5;
}
.product-price {
font-size: 1.4em;
font-weight: bold;
color: #10b981;
margin: 0;
}
.product-btn {
display: inline-block;
margin-top: 14px;
padding: 10px 28px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: #fff;
border-radius: 30px;
text-decoration: none;
font-size: 0.9em;
transition: opacity 0.2s;
}
.product-btn:hover {
opacity: 0.85;
}
</style>
</head>
<body>
<h1 class="section-title">📦 Наши товары</h1>
<div class="product-grid">
<div class="product-card">
<div class="product-icon">📱</div>
<h3>Смартфон</h3>
<p class="product-desc">6.7" экран, 128GB памяти</p>
<p class="product-price">49 990 ₽</p>
<a href="#" class="product-btn">Купить</a>
</div>
<div class="product-card">
<div class="product-icon">💻</div>
<h3>Ноутбук</h3>
<p class="product-desc">15.6", 16GB RAM, SSD 512GB</p>
<p class="product-price">89 990 ₽</p>
<a href="#" class="product-btn">Купить</a>
</div>
<div class="product-card">
<div class="product-icon">🎧</div>
<h3>Наушники</h3>
<p class="product-desc">Беспроводные, ANC</p>
<p class="product-price">7 490 ₽</p>
<a href="#" class="product-btn">Купить</a>
</div>
<div class="product-card">
<div class="product-icon">⌚</div>
<h3>Умные часы</h3>
<p class="product-desc">GPS, пульсометр, вода</p>
<p class="product-price">24 990 ₽</p>
<a href="#" class="product-btn">Купить</a>
</div>
<div class="product-card">
<div class="product-icon">📷</div>
<h3>Камера</h3>
<p class="product-desc">24MP, 4K видео</p>
<p class="product-price">55 000 ₽</p>
<a href="#" class="product-btn">Купить</a>
</div>
<div class="product-card">
<div class="product-icon">🖨️</div>
<h3>Принтер</h3>
<p class="product-desc">Лазерный, двусторонняя печать</p>
<p class="product-price">12 990 ₽</p>
<a href="#" class="product-btn">Купить</a>
</div>
</div>
</body>
</html>
Давай разберём, что здесь использует flexbox:
.product-grid—display: flexсflex-wrap: wrapиgap: 24px. Это создаёт сетку, где карточки автоматически переносятся на новую строку.justify-content: center— центрирует весь ряд карточек..product-icon—display: flexсalign-items: centerиjustify-content: center. Иконка идеально отцентрирована в кружке..product-btn—display: inline-block(не flex, но тоже для inline-раскладки).
Обрати внимание: мы не использовали ни одного float, clearfix или display: inline-block с маржинами. Всё сделано чистым flexbox'ом.
А вот ещё один пример — центрирование любого содержимого. Это очень частый паттерн:
<div class="hero">
<div class="hero-content">
<h1>Добро пожаловать!</h1>
<p>Мы рады видеть вас на нашем сайте</p>
<a href="#" class="btn">Узнать больше</a>
</div>
</div>
<style>
.hero {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea, #764ba2);
color: #fff;
text-align: center;
padding: 20px;
}
.hero h1 {
font-size: 3em;
margin: 0 0 12px;
}
.hero p {
font-size: 1.2em;
opacity: 0.9;
margin: 0 0 24px;
}
.btn {
display: inline-block;
padding: 14px 36px;
background: #fff;
color: #667eea;
border-radius: 30px;
text-decoration: none;
font-weight: bold;
transition: transform 0.2s;
}
.btn:hover {
transform: scale(1.05);
}
</style>
В этом примере .hero — flex-контейнер на всю высоту экрана (min-height: 100vh). align-items: center и justify-content: center центрируют дочерний .hero-content идеально посередине. Контент может быть любой высоты — он всегда будет по центру.
Давай подведём итог. Вот шпаргалка по flexbox:
/* FLEXBOX — ШПАРГАЛКА */
/* Родитель (контейнер) */
display: flex;
flex-direction: row | column;
flex-wrap: wrap | nowrap;
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
align-items: stretch | flex-start | flex-end | center | baseline;
gap: 16px;
/* Ребёнок (flex-элемент) */
flex: 1; /* растянуться на всё свободное место */
flex: 0 0 200px; /* не сжиматься, не расти, ширина 200px */
align-self: center; /* своё выравнивание (переопределяет align-items) */
order: 1; /* порядок (по умолчанию 0) */
Главное, что нужно запомнить:
display: flexвключает flexbox на контейнере- Главная ось —
flex-direction(row или column) justify-content— вдоль главной осиalign-items— вдоль поперечной осиgap— расстояние между элементами (удобно!)flex-wrap: wrap— перенос на новую строку- Комбинация
justify-content: center+align-items: center— идеальное центрирование
Flexbox — это база современной вёрстки. Научись чувствовать его, и ты сможешь сверстать почти любую раскладку без труда. В следующем уроке мы перейдём к позиционированию — ещё одному важному инструменту CSS.
Урок 4.4: Flexbox
9 вопросов