🕐 9 хв читання

Позиціювання блочних елементів

Конспект лекції: Flexbox, CSS Grid, семантичні теги header/nav/footer, схлопування margin, псевдокласи

Flexbox — основи

Flexbox (Flexible Box Layout) — інструмент для розташування елементів у рядок або стовпець. Дозволяє гнучко керувати розкладкою без хаків.

Як увімкнути?

display: flex задається батьківському елементу (flex-контейнеру). Після цього його дочірні елементи стають flex-елементами.

.header {
    display: flex;
    /* Дочірні елементи розташуються горизонтально */
}
Flex-контейнер поводиться як блочний елемент (займає всю ширину). Єдина відмінність — доступні спеціальні властивості для керування дочірніми елементами.

Принцип двох осей

У Flexbox є дві осі:

  • Головна вісь (main axis) — напрямок, вздовж якого розташовуються flex-елементи. За замовчуванням: зліва направо.
  • Поперечна вісь (cross axis) — перпендикулярна головній. За замовчуванням: згори вниз.
Уникайте термінів «вліво», «вправо», «вгору», «вниз» при роботі з Flexbox. Осі можна перевертати, тому оперуйте поняттями: «початок/кінець головної осі», «початок/кінець поперечної осі».

Вирівнювання по висоті

За замовчуванням 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: grid
  • overflow (зі значенням, відмінним від 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)
Нумерація починається з 1 (не з 0, як у програмуванні).

Формула 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

Стилі за замовчуванням відрізняються між браузерами. Є два підходи для уніфікації:

Normalize CSS
  • Приводить стилі до єдиного вигляду
  • Зберігає корисні стилі за замовчуванням
  • Підходить для більшості сайтів
  • Рекомендований підхід
Reset CSS
  • Повністю скидає всі стилі
  • Потрібно задавати все з нуля
  • Підходить для веб-додатків, ігор
  • Використовується рідше
Не використовуйте * { margin: 0; padding: 0; } як заміну Normalize — це скидає корисні відступи у статтях, списках, заголовках, і доведеться додавати їх вручну.

CSS Grid — двовимірна розкладка

CSS Grid Layout — інструмент для створення двовимірних розкладок (рядки і стовпці одночасно). Повністю підтримується усіма сучасними браузерами.

Flexbox vs Grid

Flexbox
  • Одновимірний (рядок або стовпець)
  • Елементи визначають розмір
  • Ідеальний для компонентів
  • Шапка, меню, картка, форма
Grid
  • Двовимірний (рядки і стовпці)
  • Контейнер визначає розкладку
  • Ідеальний для сторінок
  • Сітка карток, макет сторінки
Flexbox і Grid — не конкуренти, а партнери. Grid — для загальної структури сторінки, Flexbox — для компонентів всередині. Використовуйте обидва.

Як увімкнути?

.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;  /* вся ширина */
}
Результат: шапка на всю ширину, бічна панель (250px) + основний контент (решта), підвал на всю ширину. Усе — без Flexbox-хаків.

Коли що використовувати

Задача Інструмент Чому
Шапка: лого + меню 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). Використовуйте обидва
🔍
Почніть вводити назву лекції або тему