Верстка сайту з використанням 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
.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 дні |







