Вёрстка сайта с использованием CSS Flexbox
Flexbox — одномерная система раскладки для выравнивания элементов в строку или столбец. Это основной инструмент для компонентного уровня: навигация, карточки, кнопки, формы, тулбары. Знание 8–10 ключевых свойств решает 80% задач выравнивания.
Ось и перпендикуляр
Главная концепция Flexbox — главная ось (main axis) и поперечная ось (cross axis):
.container {
display: flex;
flex-direction: row; /* Горизонтально (по умолчанию) */
/* или: column */ /* Вертикально */
/* или: row-reverse */ /* Горизонтально, справа налево */
}
justify-content выравнивает по главной оси, align-items — по поперечной. Путаница именно здесь — запоминается, если помнить что justify = главная = направление flex-direction.
Навигация
.nav {
display: flex;
align-items: center; /* Центрировать вертикально */
gap: 8px;
padding: 0 24px;
height: 64px;
}
.nav__logo {
margin-inline-end: auto; /* Толкает всё остальное вправо */
}
.nav__links {
display: flex;
gap: 4px;
list-style: none;
margin: 0;
padding: 0;
}
.nav__cta {
margin-inline-start: 16px; /* Небольшой отступ от ссылок */
}
margin-inline-end: auto на одном элементе — классический Flexbox-трюк для разделения группы. Лого слева, всё остальное справа — без абсолютного позиционирования.
Центрирование
Самая частая задача — прокляте «центрировать по вертикали»:
/* Центрирование в родителе */
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Или короче */
.hero {
display: flex;
place-content: center; /* Оба свойства одновременно */
min-height: 100vh;
}
/* Центрировать один элемент внутри flex-контейнера */
.card__icon {
align-self: center;
}
Карточки с равной высотой
.cards {
display: flex;
gap: 24px;
flex-wrap: wrap; /* Перенос на новую строку */
}
.card {
flex: 1 1 280px; /* grow: 1, shrink: 1, basis: 280px */
display: flex;
flex-direction: column;
}
/* Кнопка всегда внизу карточки, независимо от длины текста */
.card__body {
flex: 1; /* Занять всё доступное пространство */
}
.card__action {
margin-top: auto; /* Или: align-self: flex-end на родителе column */
}
flex: 1 1 280px — сокращение трёх свойств: flex-grow: 1 (растягивается), flex-shrink: 1 (сжимается), flex-basis: 280px (минимальная ширина). Карточки заполняют ряд, но не становятся уже 280px.
Форма
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
/* Поле с кнопкой в одну строку */
.input-group {
display: flex;
}
.input-group__field {
flex: 1;
border-right: none;
border-radius: 6px 0 0 6px;
}
.input-group__btn {
border-radius: 0 6px 6px 0;
white-space: nowrap;
}
/* Строка полей */
.form-row {
display: flex;
gap: 16px;
}
.form-row .form-group { flex: 1; }
/* Имя занимает больше места чем индекс */
.form-row .form-group--name { flex: 3; }
.form-row .form-group--zip { flex: 1; }
Иконка + текст (распространённый паттерн)
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
border-radius: 6px;
font-weight: 500;
cursor: pointer;
border: none;
background: var(--color-accent);
color: white;
transition: background 150ms ease;
}
.btn__icon {
width: 16px;
height: 16px;
flex-shrink: 0; /* Иконка не сжимается при длинном тексте */
}
inline-flex — кнопка ведёт себя как inline-block, но внутри — flex-контекст для выравнивания иконки и текста.
Sidebar layout
.sidebar-layout {
display: flex;
align-items: flex-start; /* Sidebar не растягивается на всю высоту */
gap: 32px;
}
.sidebar-layout__sidebar {
flex: 0 0 280px; /* Фиксированная ширина, не растягивается */
position: sticky;
top: 80px; /* Залипание при скролле */
}
.sidebar-layout__main {
flex: 1; /* Занимает оставшееся пространство */
min-width: 0; /* Решает проблему переполнения в flex-контексте */
}
min-width: 0 — критически важно для главной колонки. По умолчанию flex-item не может быть уже своего содержимого (min-width: auto). Это приводит к горизонтальному скроллу при длинных словах, таблицах, блоках кода. min-width: 0 разрешает сжатие.
flex-wrap и выравнивание строк
.tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-content: flex-start; /* Строки прижаты к верху, не растянуты */
}
/* Тег занимает ровно столько места сколько нужно */
.tag {
flex: 0 1 auto;
padding: 4px 12px;
border-radius: 100px;
background: var(--color-surface);
border: 1px solid var(--color-border);
white-space: nowrap;
}
Ошибки новичков
display: flex на <img>. Изображение становится flex-контейнером, что ломает его поведение. Обёртка в <figure> или <div> — лучшее решение.
Забыть flex-shrink: 0 на иконках. При нехватке места flex сожмёт иконку раньше текста, и она станет деформированной.
justify-content: space-between для трёх элементов и более. Последний ряд при flex-wrap расстворится — крайние элементы растянутся к краям. Решение:
/* Плохо при wrap */
.cards { justify-content: space-between; }
/* Хорошо */
.cards {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card { flex: 1 1 280px; max-width: calc(33.333% - 16px); }
height: 100% не работает в flex. Дочерний элемент растягивается по умолчанию если align-items не flex-start. Для явного заполнения: align-self: stretch (по умолчанию) или flex: 1 по вертикальной оси.
Сроки
| Задача | Время |
|---|---|
| Навигация (header с flex-раскладкой) | 0.5 дня |
| Страница с карточками и sidebar | 1 день |
| Полная Landing page (Flexbox-based) | 1.5–2 дня |







