Позиціювання блочних елементів
Конспект лекції: Flexbox, CSS Grid, семантичні теги header/nav/footer, схлопування margin, псевдокласи
Flexbox — основи
Flexbox (Flexible Box Layout) — інструмент для розташування елементів у рядок або стовпець. Дозволяє гнучко керувати розкладкою без хаків.
Як увімкнути?
display: flex задається батьківському елементу (flex-контейнеру). Після цього
його дочірні елементи стають flex-елементами.
.header {
display: flex;
/* Дочірні елементи розташуються горизонтально */
}
Принцип двох осей
У Flexbox є дві осі:
- Головна вісь (main axis) — напрямок, вздовж якого розташовуються flex-елементи. За замовчуванням: зліва направо.
- Поперечна вісь (cross axis) — перпендикулярна головній. За замовчуванням: згори вниз.
Вирівнювання по висоті
За замовчуванням flex-елементи в одному рядку вирівнюються по висоті найбільшого елемента. Це дуже зручно для карток однакової висоти.
flex-direction — напрямок головної осі
Керує напрямком головної осі (і, відповідно, розташуванням flex-елементів).
| Значення | Головна вісь | Результат |
|---|---|---|
row (за замовчуванням) |
→ зліва направо | Елементи в рядок |
row-reverse |
← справа наліво | Елементи в рядок, у зворотному порядку |
column |
↓ згори вниз | Елементи стовпцем |
column-reverse |
↑ знизу вгору | Елементи стовпцем, у зворотному порядку |
flex-wrap — перенос елементів
За замовчуванням flex-елементи не переносяться на новий рядок — вони стискаються.
| Значення | Поведінка |
|---|---|
nowrap (за замовчуванням) |
Елементи стискаються, не переносяться |
wrap |
Елементи переносяться на новий рядок, якщо не вміщуються |
wrap-reverse |
Перенос у зворотному напрямку поперечної осі |
wrap переноситься на новий рядок. При
nowrap — усі чотири стискаються.
Практичний приклад: шапка сайту
Типова задача: логотип ліворуч, меню праворуч — горизонтально.
<!-- HTML -->
<header class="header">
<a href="/" class="logo">
<img src="logo.svg" alt="Логотип">
</a>
<nav class="menu">
<ul class="menu-list">
<li class="menu-list-item">
<a href="#">Головна</a>
</li>
<li class="menu-list-item">
<a href="#">Про нас</a>
</li>
</ul>
</nav>
</header>
/* CSS */
.header {
display: flex; /* логотип і nav — в рядок */
}
.menu-list {
display: flex; /* пункти меню — в рядок */
margin: 0;
padding: 0;
list-style-type: none;
}
display: flex задається батьку тих елементів, які треба розташувати. Якщо у
контейнера лише один дочірній елемент — Flexbox нічого не змінить.
Теги <header>, <nav>, <footer>
<header> — шапка
- Вступна, допоміжна інформація перед основним контентом.
- Може бути шапкою сайту (в
<body>), статті (в<article>), секції (в<section>). - На сторінці може бути кілька
<header>в різних контекстах.
<nav> — навігація
- Блок основної навігації сайту або хлібних крихт (breadcrumbs).
- Основне меню — ненумерований список
<ul>(порядок не важливий). - Хлібні крихти — нумерований список
<ol>(порядок важливий).
<footer> — підвал
- Допоміжна інформація після основного контенту.
- Як і
<header>, може бути підвалом сайту, статті, секції. - Типовий вміст: копірайт, контакти, посилання на соцмережі, дата публікації.
<div> на семантичний тег — перевіряйте, чи браузер не
додав стилі за замовчуванням (User Agent Stylesheet). Для <header> і
<footer> зазвичай лише display: block, проблем немає.
Стилізація навігаційного списку
При використанні <ul> для меню потрібно скинути стилі за замовчуванням:
.menu-list {
margin: 0;
padding: 0;
list-style-type: none; /* прибрати маркери */
}
list-style-type) потрібні для списків у тексті статей. У навігації,
картках, табах — завжди прибирайте їх.
Схлопування margin (margin collapsing)
Вертикальні margin-top і margin-bottom блочних елементів мають особливу поведінку:
1. Схлопування між сусідами
Коли margin-bottom одного елемента зустрічається з margin-top наступного — вони
не додаються, а обирається більший.
margin-bottom: 20px, параграф — margin-top: 10px. Відстань між ними
= 20px (більший), а не 30px.
2. Вихід margin за межі батька
margin-top першого дочірнього і margin-bottom останнього дочірнього можуть
«витікати» за межі батьківського елемента.
Як запобігти витіканню?
Margin залишається всередині батька, якщо у батька є:
padding(хоча бpadding-top: 1px)border(хоча бborder-top: 1px solid transparent)display: flexабоdisplay: gridoverflow(зі значенням, відмінним відvisible)
padding або border батьку,
поведінка margin може раптово змінитися. Це часта причина «непояснюваних» зсувів у верстці.
Псевдокласи :nth-child() та :nth-of-type()
Псевдокласи дозволяють вибирати елементи за їхньою позицією серед сусідів. Синтаксис: селектор:псевдоклас
(через двокрапку).
Різниця між nth-child і nth-of-type
| Псевдоклас | Рахує |
|---|---|
:nth-child() |
Усі дочірні елементи незалежно від типу тегу |
:nth-of-type() |
Окремо кожний тип тегу (<div> — свій рахунок, <article> —
свій)
|
Значення
| Значення | Що обирає | Приклад |
|---|---|---|
odd |
Непарні: 1, 3, 5, 7… | .card:nth-child(odd) |
even |
Парні: 2, 4, 6, 8… | .card:nth-child(even) |
число (напр. 3) |
Конкретний елемент | .card:nth-child(3) |
формула an+b |
Кожний a-й, починаючи з b-го | .card:nth-child(2n+3) |
Формула an+b — як працює
- a — крок (кожний a-й елемент)
- n — змінна (браузер підставляє 0, 1, 2, 3…)
- b — зміщення (з якого елемента починати)
2n+3: починаючи з 3-го, кожний 2-й.n=0 → 3, n=1 → 5, n=2 → 7, n=3 → 9…
Результат: 3-й, 5-й, 7-й, 9-й елементи.
Типові комбінації
| Формула | Еквівалент | Обирає |
|---|---|---|
2n |
even |
Кожний парний |
2n+1 |
odd |
Кожний непарний |
n+2 |
— | Усі, починаючи з 2-го (тобто всі крім першого) |
3n |
— | Кожний 3-й: 3, 6, 9… |
-n+3 |
— | Перші 3 елементи |
Скорочені псевдокласи
| Псевдоклас | Еквівалент | Обирає |
|---|---|---|
:first-child |
:nth-child(1) |
Перший елемент |
:last-child |
— | Останній елемент |
:first-of-type |
:nth-of-type(1) |
Перший елемент кожного типу |
:last-of-type |
— | Останній елемент кожного типу |
Практика: відступи між картками
Типова задача: список карток із відступами між ними, але без зайвого відступу зверху.
Рішення через nth-child
/* Відступ для всіх карток, починаючи з другої */
.post:nth-child(n+2) {
margin-top: 35px;
}
Альтернативне рішення
/* Усім задати margin-top */
.post {
margin-top: 35px;
}
/* У першого — прибрати */
.post:first-child {
margin-top: 0;
}
Чересмужжя (кожна парна картка — інший колір)
.post:nth-child(even) {
background-color: #1a1a1a;
color: #fff;
}
Сучасний підхід: gap
Властивість gap задає відступи між flex-елементами без потреби у псевдокласах та margin-хаках:
.cards {
display: flex;
flex-direction: column;
gap: 35px; /* відступ між картками, без зайвого зверху/знизу */
}
gap повністю підтримується у Flexbox з 2021 року (усі сучасні браузери). Це
найчистіший спосіб задати відступи між елементами — gap не створює зайвих margin ні зверху, ні
знизу.
Псевдоелементи ::before та ::after
Псевдоелементи створюють віртуальні елементи в DOM для стилізації, не засмічуючи HTML.
::before— вставляє контент перед вмістом елемента.::after— вставляє контент після вмісту елемента.- Обов'язково потрібна властивість
content.
Типові застосування
- Зірочки обов'язкових полів у формах
- Кастомні маркери для списків
- Декоративні стрілки, іконки
- Затемнення фону (overlay)
/* Зірочка для обов'язкового поля */
.required::after {
content: " *";
color: red;
}
::before), але працюють і з однією
(:before). Рекомендується два для розрізнення з псевдокласами.
Normalize CSS vs Reset CSS
Стилі за замовчуванням відрізняються між браузерами. Є два підходи для уніфікації:
- Приводить стилі до єдиного вигляду
- Зберігає корисні стилі за замовчуванням
- Підходить для більшості сайтів
- Рекомендований підхід
- Повністю скидає всі стилі
- Потрібно задавати все з нуля
- Підходить для веб-додатків, ігор
- Використовується рідше
* { margin: 0; padding: 0; } як заміну Normalize — це скидає
корисні відступи у статтях, списках, заголовках, і доведеться додавати їх вручну.
CSS Grid — двовимірна розкладка
CSS Grid Layout — інструмент для створення двовимірних розкладок (рядки і стовпці одночасно). Повністю підтримується усіма сучасними браузерами.
Flexbox vs Grid
- Одновимірний (рядок або стовпець)
- Елементи визначають розмір
- Ідеальний для компонентів
- Шапка, меню, картка, форма
- Двовимірний (рядки і стовпці)
- Контейнер визначає розкладку
- Ідеальний для сторінок
- Сітка карток, макет сторінки
Як увімкнути?
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 3 рівні стовпці */
gap: 20px; /* відступи між елементами */
}
display: grid задається батьківському елементу (grid-контейнеру). Дочірні елементи автоматично
розміщуються в сітці.
Grid: основні властивості
grid-template-columns — стовпці
Визначає кількість і ширину стовпців:
/* Три стовпці по 200px */
grid-template-columns: 200px 200px 200px;
/* Три рівні стовпці (гнучкі) */
grid-template-columns: 1fr 1fr 1fr;
/* Скорочення: 3 стовпці по 1fr */
grid-template-columns: repeat(3, 1fr);
/* Бічна панель 250px, основний контент — решта */
grid-template-columns: 250px 1fr;
fr (fraction) — частка вільного простору. 1fr 2fr означає:
перший стовпець отримає 1/3, другий — 2/3 доступної ширини.
grid-template-rows — рядки
/* Шапка 80px, контент гнучкий, підвал 60px */
grid-template-rows: 80px 1fr 60px;
gap — відступи
gap: 20px; /* однаковий відступ */
gap: 20px 30px; /* рядки: 20px, стовпці: 30px */
row-gap: 20px; /* тільки між рядками */
column-gap: 30px; /* тільки між стовпцями */
Grid: розміщення елементів
Автоматичне розміщення
За замовчуванням елементи заповнюють сітку по порядку, зліва направо, рядок за рядком.
Ручне розміщення
Можна вказати, які рядки та стовпці займає елемент:
.hero {
grid-column: 1 / 3; /* від 1-ї до 3-ї лінії (2 стовпці) */
grid-row: 1 / 2; /* перший рядок */
}
.sidebar {
grid-column: 3; /* третій стовпець */
grid-row: 1 / 3; /* від 1-го до 3-го рядка */
}
span: grid-column: span 2 означає «займи 2 стовпці від
поточної позиції».
Grid: практичні приклади
Сітка карток (адаптивна)
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
auto-fill + minmax() — картки автоматично переносяться на новий рядок, коли ширина
екрана зменшується. Без медіа-запитів!
Класичний макет сторінки
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.page-header {
grid-column: 1 / -1; /* вся ширина */
}
.page-footer {
grid-column: 1 / -1; /* вся ширина */
}
Коли що використовувати
| Задача | Інструмент | Чому |
|---|---|---|
| Шапка: лого + меню | Flexbox | Один рядок, два елементи |
| Пункти меню в рядок | Flexbox | Одновимірний список |
| Сітка карток 3×N | Grid | Двовимірна сітка |
| Макет сторінки (шапка + sidebar + контент + підвал) | Grid | Складна двовимірна структура |
| Центрування одного елемента | Flexbox або Grid | Обидва підходять |
| Кнопки в ряд із відступами | Flexbox + gap | Простий рядок із gap |
Підсумок
| Тема | Ключове |
|---|---|
| Flexbox | display: flex на батьку → дочірні в рядок |
flex-direction |
row | column | row-reverse | column-reverse |
flex-wrap |
nowrap (стискає) | wrap (переносить) |
<header> |
Шапка сайту / секції / статті |
<nav> |
Основна навігація або хлібні крихти |
<footer> |
Підвал сайту / секції / статті |
| Margin collapsing | Вертикальні margin схлопуються (обирається більший) |
:nth-child() |
Вибір за позицією: odd, even, an+b |
::before / ::after |
Віртуальні елементи для стилізації (потрібен content) |
| Normalize CSS | Уніфікує стилі між браузерами (рекомендований) |
gap |
Відступи між flex/grid-елементами без margin-хаків |
| CSS Grid | display: grid — двовимірна розкладка (рядки + стовпці) |
grid-template-columns |
repeat(3, 1fr), minmax(), auto-fill |
| Flexbox vs Grid | Flex — компоненти (1D); Grid — сторінки (2D). Використовуйте обидва |