🕐 14 хв читання

Позиціювання flex-елементів

Конспект лекції: align-items, align-self, flex-wrap, order, flex-grow та інші властивості Flexbox

1. align-items — вирівнювання по додатковій осі

Властивість align-items задається flex-контейнеру і керує розміщенням елементів уздовж додаткової (cross) осі.

Значення Поведінка
flex-start Притиснути до початку додаткової осі
flex-end Притиснути до кінця додаткової осі
center Центрувати по додатковій осі
baseline Вирівняти по базовій лінії тексту (корисно, коли різний font-size)
stretch (за замовчуванням) Розтягнути елементи на всю висоту контейнера
Пам'ятайте: «вертикаль» і «горизонталь» у Flexbox — умовні. Якщо flex-direction: column, осі міняються місцями: головна йде зверху вниз, додаткова — зліва направо.

2. justify-content — вирівнювання по головній осі

Властивість justify-content керує розподілом елементів та вільного простору уздовж головної (main) осі.

Значення Поведінка
flex-start (за замовчуванням) Притиснути до початку головної осі
flex-end Притиснути до кінця головної осі
center Центрувати елементи
space-between Крайні елементи притиснуті до меж, вільний простір — рівномірно між елементами
space-around Рівні проміжки навколо кожного елемента (крайні = половина внутрішніх)
space-evenly Усі проміжки абсолютно рівні (і між елементами, і від краю)

Центрування модального вікна

.popup {
    display: flex;
    justify-content: center;  /* по горизонталі */
    align-items: center;      /* по вертикалі */
}

3. flex-shrink — коефіцієнт стиснення

Властивість flex-shrink визначає, чи може елемент всередині flex-контейнера зменшуватися, коли зменшується розмір екрану.

Синтаксис

flex-shrink: 1;  /* за замовчуванням — елемент стискається */
flex-shrink: 0;  /* елемент НЕ стискається */

Значення — будь-яке додатне число від 0 і вище. За замовчуванням — 1, тобто елемент зменшується разом із контейнером.

Якщо поставити 0 — елемент зберігатиме свої розміри незалежно від ширини екрану.

Практичний приклад: пошуковий рядок

Уявімо пошуковий рядок з трьома частинами: підказка зліва, input по центру, кнопка «Шукати» справа. Якщо задати всім елементам розміри у відсотках — на маленьких екранах підказка розіб'ється на додаткові рядки, а текст кнопки обріжеться.

Рішення: заборонити підказці та кнопці стискатися:

/* Підказка і кнопка — фіксовані */
.hint, .button {
  flex-shrink: 0;
}

/* Input займає решту простору */
.search-input {
  flex-grow: 1;
}

4. flex-grow — коефіцієнт розтягування

Властивість flex-grow визначає, чи може елемент розтягуватися, щоб зайняти вільний простір.

Синтаксис

flex-grow: 0;  /* за замовчуванням — не розтягується */
flex-grow: 1;  /* розтягується, займає вільний простір */
flex-grow: 2;  /* займає вдвічі більше, ніж flex-grow: 1 */

На відміну від flex-shrink, різні значення flex-grow дійсно дають різний результат. Елемент із flex-grow: 2 займе вдвічі більше вільного простору, ніж елемент із flex-grow: 1.

Комбінація flex-shrink і flex-grow

Для пошукового рядка: підказка та кнопка не стискаються і не розтягуються, а input займає весь вільний простір:

.hint, .button {
  flex-shrink: 0;
  flex-grow: 0;
}

.search-input {
  flex-grow: 1;
}

Тепер на будь-якому екрані ліва і права частини займають рівно стільки місця, скільки потрібно для їхнього вмісту, а input заповнює решту.

5. flex-basis та розміри елементів

Властивість flex-basis визначає початковий розмір елемента у flex-контейнері. Це аналог width для горизонтальних та height для вертикальних flex-контейнерів.

Синтаксис

flex-basis: 250px;
flex-basis: 50%;
flex-basis: auto;  /* розмір за вмістом */

Пріоритетність

flex-basis — це не жорстка ширина, а максимальна бажана величина. Якщо в контейнері не вистачає місця, елементи стиснуться.

  • flex-basis важливіша за width — якщо задати обидва, width ігнорується
  • min-width / max-width важливіші за flex-basis

У вертикальному flexbox

Якщо задати flex-direction: column, то flex-basis визначає висоту елемента (замість ширини). Аналогічно: height ігнорується, а min-height / max-height мають вищий пріоритет.

Правило

Не змішуйте flex-basis із width / height. Використовуйте або flex-basis, або width (height) разом із min-/max- варіантами.

6. Скорочений запис flex

Властивості flex-grow, flex-shrink і flex-basis можна записати скорочено через flex:

flex: <flex-grow> <flex-shrink> <flex-basis>;

Варіанти запису

Запис Еквівалент Опис
flex: auto flex: 1 1 auto Розтягується, стискається, розмір за вмістом
flex: initial flex: 0 1 auto Значення за замовчуванням: не розтягується, стискається
flex: none flex: 0 0 auto Не розтягується, не стискається — фіксований розмір
flex: 1 flex: 1 1 0 Розтягується і стискається пропорційно
flex: 2 flex: 2 1 0 Займає вдвічі більше простору, ніж flex: 1

Друге значення — число чи розмір?

Браузер автоматично визначає: якщо друге значення — просте число (1, 2, 3) — це flex-shrink. Якщо це величина з одиницями (px, %, rem) — це flex-basis:

flex: 0 auto;    /* flex-grow: 0, flex-basis: auto (flex-shrink: 1 за замовчуванням) */
flex: 1 200px;   /* flex-grow: 1, flex-basis: 200px */

Спрощення пошукового рядка

.hint, .button {
  flex: none;   /* не стискається, не розтягується */
}

.search-input {
  flex: 1;      /* займає весь вільний простір */
}

7. Розподіл простору через flex

Замість відсотків можна використовувати flex для розподілу простору між елементами. Числа визначають пропорції:

/* Три колонки: 20% + 30% + 50% */
.col-1 { flex: 2; }  /* 2/10 = 20% */
.col-2 { flex: 3; }  /* 3/10 = 30% */
.col-3 { flex: 5; }  /* 5/10 = 50% */

Сума значень flex визначає «загальну кількість частин». Кожен елемент отримує свою частку. Наприклад, 2 + 3 + 5 = 10 частин, і перший елемент займає 2/10 простору.

Переваги перед відсотками

  • Додавання нових елементів — простір перерозподіляється автоматично
  • Однакові flex: 1 для всіх — елементи завжди однакового розміру
  • На мобільних — вимикаєте display: flex, і блоки стають звичайними div, які падають один під одного

Адаптивна колонкова верстка

.container {
  display: flex;
}

.main { flex: 2; }   /* 2/3 простору */
.sidebar { flex: 1; } /* 1/3 простору */

@media (max-width: 768px) {
  .container {
    display: block; /* відключаємо flex — блоки падають один під одного */
  }
}

8. Властивість order

Властивість order змінює порядок відображення елементів у flex-контейнері без зміни HTML. Працює лише в flexbox.

Синтаксис

order: 0;   /* за замовчуванням */
order: 1;   /* відобразити пізніше */
order: -1;  /* відобразити раніше */

Значення — будь-яке ціле число (додатне або від'ємне). Чим менше число — тим раніше елемент з'являється:

  • У горизонтальному flexbox: менше число — лівіше
  • У вертикальному flexbox: менше число — вище

Приклад: картка новини

На десктопі: зображення → заголовок → теги → текст. На мобільному дизайнер хоче теги під текстом. Рішення — додати order через медіазапит:

.card {
  display: flex;
  flex-direction: column;
}

@media (max-width: 480px) {
  .card-tags {
    order: 1; /* 1 > 0, тому теги переміщуються вниз */
  }
}

На десктопі всі елементи мають order: 0 і відображаються в порядку HTML. На мобільному теги отримують order: 1 і переміщуються вниз.

Семантика HTML

Перевірити семантику верстки можна, вимкнувши CSS у браузері. Без стилів сторінка повинна читатися логічно: заголовки — це заголовки, списки — це списки (а не div зі span), навігація — це <nav> з <ul>.

9. align-content — вирівнювання рядків flex-контейнера

Властивість align-content керує розподілом рядків багаторядкового flex-контейнера по додатковій осі (працює лише з flex-wrap: wrap).

Значення Поведінка
flex-start Рядки притиснуті до початку
flex-end Рядки притиснуті до кінця
center Рядки по центру
space-between Крайні рядки притиснуті до меж, простір між рядками рівномірний
space-around Рівні проміжки навколо кожного рядка
stretch (за замовчуванням) Рядки розтягуються на всю висоту контейнера

10. align-self — індивідуальне вирівнювання flex-елемента

Властивість align-self дозволяє перевизначити align-items для одного конкретного flex-елемента по додатковій осі.

.container {
    display: flex;
    align-items: flex-start;
}

.button {
    align-self: center;  /* Тільки ця кнопка по центру */
}
Значення Поведінка
auto (за замовчуванням) Успадковує значення align-items контейнера
flex-start Притискає до початку додаткової осі
flex-end Притискає до кінця додаткової осі
center Центрує по додатковій осі
stretch Розтягує на всю висоту рядка
baseline Вирівнює по базовій лінії тексту

Альтернатива: margin auto

Центрування одного елемента можна зробити і через margin-top: auto; margin-bottom: auto;, але align-self: center — більш явний і семантичний спосіб.

11. Центрування елементів через margin: auto

У flex-контейнері margin: auto працює і по горизонталі, і по вертикалі (на відміну від звичайного потоку, де margin-top: auto = 0).

.container {
    display: flex;
    width: 400px;
    height: 400px;
}

.box {
    width: 100px;
    height: 100px;
    margin: auto;  /* Центрує і горизонтально, і вертикально */
}

margin auto у flex — розподіл елементів

Елемент 1 Елемент 2 Результат
margin-left: auto Елемент притискається вправо
margin-right: auto margin-left: auto Елементи розходяться по кутах
margin-right: auto margin-right: auto Обидва притискаються вліво
margin-left: auto margin-left: auto Обидва притискаються вправо
margin: auto для обох Обидва по центру
Порівняння з justify-content: margin: auto керує окремими елементами, тоді як justify-content — усіма елементами контейнера одразу.

12. position: fixed — фіксоване позиціювання

position: fixed поводиться майже як absolute, але з однією ключовою відмінністю: елемент фіксується при прокрутці.

Спільне з absolute

  • Ширина/висота рахуються за контентом (а не 100% батька)
  • Елемент невидимий для сусідів і батька
  • Можна задавати width/height навіть інлайновим елементам
  • Керується через top, right, bottom, left

Відмінність від absolute

absolute fixed
Точка відліку Найближчий батько з position: relative (або viewport, якщо немає) Завжди viewport (вікно браузера)
При прокрутці Прокручується разом зі сторінкою Залишається на місці
Реагує на relative батька Так Ні

Типові приклади fixed

  • Фіксована шапка — завжди вгорі при прокрутці
  • Модальне вікно — перекриває весь екран, не рухається
  • Кнопка «Нагору» — завжди в куті екрана
  • Чат-бот — віконце підтримки внизу справа
  • Бічне меню (dashboard) — фіксована навігація зліва
/* Модальне вікно — fixed замість absolute */
.popup {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 9999;          /* гарантовано поверх усього */
    display: flex;
    justify-content: center;
    align-items: center;
}
Великий z-index (9999) використовується для модальних вікон, щоб гарантовано перекрити всі інші елементи на сторінці — фіксовані шапки, чат-боти тощо.

13. display: none — повне приховування

display: none повністю прибирає елемент зі сторінки — ніби його видалили з HTML.

Спосіб приховування Видимий? Займає місце? Інтерактивний? Доступний для скрінрідерів?
display: none Ні Ні Ні Ні
opacity: 0 Ні Так Так (можна клікнути) Так
Візуальне приховування (clip-path) Ні Ні Так (Tab) Так
Коли що використовувати:
  • display: none — елемент не повинен існувати на сторінці (закрите модальне вікно, прихований таб)
  • Візуальне приховування (clip-path) — елемент потрібен, але не видимий (текст для скрінрідерів, приховані label)

14. Показ/приховування через класи (popup-паттерн)

Класичний підхід для модальних вікон, випадаючих меню, табів:

/* Базовий стан — приховано */
.popup {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: none;          /* приховано */
}

/* Активний стан — показано */
.popup--active {
    display: flex;           /* перекриває display: none */
    justify-content: center;
    align-items: center;
}

Як це працює з JavaScript

// Закрити popup при кліку на хрестик
document.querySelector('.popup__close')
    .addEventListener('click', function() {
        document.querySelector('.popup--active')
            .classList.remove('popup--active');
    });

JavaScript лише додає/видаляє клас. Вся стилізація — у CSS.

Порядок має значення! Клас .popup--active повинен бути нижче в CSS, ніж .popup. При однаковій специфічності браузер застосує той, що стоїть останнім.

15. Специфічність CSS-селекторів

Коли до одного елемента застосовуються кілька правил з однаковою властивістю — браузер обирає за коефіцієнтом специфічності.

Формула: 4 числа

Позиція Що рахуємо Приклад
A Inline-стиль (style="...") 0 або 1
B Кількість id #header → 1
C Кількість класів, псевдокласів, атрибутів .nav:hover → 2
D Кількість елементів (тегів), псевдоелементів div::before → 2

Приклади розрахунку

Селектор A B C D
span 0 0 0 1
.slogan 0 0 1 0
#slogan 0 1 0 0
style="..." 1 0 0 0
ul > .widget.socials 0 0 2 1
.widget.socials 0 0 2 0
div.widget:hover 0 0 2 1
Це 4 окремі числа, не одне! 0,0,0,20 все одно менше за 0,0,1,0. Селектор по класу завжди специфічніший за будь-яку кількість тегів.

16. Що НЕ впливає на специфічність

  • Дочірній селектор > — не додає ваги
  • Сусідній селектор + — не додає ваги
  • Загальний сусідній ~ — не додає ваги
  • Вкладений селектор (пробіл) — не додає ваги
/* Обидва мають специфічність 0,0,2,1 */
ul > .widget.socials  { ... }
ul .widget.socials    { ... }
Контрінтуїтивно: дочірній селектор > «звужує» вибірку, але не підвищує специфічність.

17. Однакова специфічність → порядок у CSS

Якщо два селектори мають однакову специфічність, перемагає той, що розташований нижче у CSS-файлі.

/* Специфічність обох: 0,0,1,0 */
.slogan { font-size: 40px; }  /* ← програє */
.text   { font-size: 20px; }  /* ← переможе */
Порядок класів у HTML не має значення. Неважливо, чи написано class="slogan text" чи class="text slogan". Має значення лише порядок правил у CSS.

Практичне застосування

Тому сторонні стилі (бібліотеки, віджети) підключають до ваших стилів:

<!-- 1. Спочатку — сторонні стилі -->
<link rel="stylesheet" href="widget.css">
<!-- 2. Потім — ваші стилі -->
<link rel="stylesheet" href="style.css">

Завдяки цьому ваш селектор з такою ж специфічністю перекриє стилі бібліотеки.

18. Дочірній селектор > та комбінування з тегом

Вкладений vs дочірній

Селектор Що обирає
.widget div Усі div всередині .widget (на будь-якому рівні вкладеності)
.widget > div Тільки безпосередні дочірні div (перший рівень)

Комбінування класу з тегом

/* Будь-який елемент з класом .card */
.card { ... }

/* Тільки <article> з класом .card */
article.card { ... }
Уникайте прив'язки до тегу! Селектор div.card жорстко прив'язує стилі до <div>. Якщо потім змінити тег на <article> — стилі зламаються. Стилізуйте за класами.

19. !important — коли інших варіантів немає

!important підвищує пріоритет конкретної властивості (не всього селектора) вище за inline-стилі:

span {
    font-size: 10px !important;  /* переможе навіть style="font-size: 20px" */
}

Якщо є два !important — перемагає той, у кого вища специфічність селектора.

!important — це «антипатерн». Ознака помилки в архітектурі CSS. Його дуже важко «виковиряти» з коду потім.
  • Не використовуйте без крайньої потреби
  • Якщо використали — завжди залишайте коментар, чому
  • Допустимі випадки: швидкий хотфікс, перекриття стороннього віджета без доступу до його CSS

20. Рекомендації щодо архітектури CSS

  • Стилізуйте за класами, не за id (id — для JavaScript)
  • Максимально плоска структура: один клас → один селектор (.popup-box, .popup-close)
  • Уникайте глибокої вкладеності: .page .main .content h1 — погано
  • Краще: .main-title — просто, зрозуміло, низька специфічність
  • Сторонні бібліотеки підключайте перед власними стилями
  • Не використовуйте !important у звичайній роботі
BEM-підхід (Block Element Modifier) допомагає підтримувати плоску специфічність: .popup, .popup__box, .popup--active — усі мають специфічність 0,0,1,0.

21. Підключення шрифтів — @font-face

Конструкція @font-face описує файл шрифта для браузера. На кожне начертання — окремий @font-face.

/* Звичайне начертання */
@font-face {
    font-family: "PT Sans";
    src: url("../fonts/pt-sans-regular.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
}

/* Жирне начертання */
@font-face {
    font-family: "PT Sans";
    src: url("../fonts/pt-sans-bold.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
}

Як браузер обирає файл

Браузер порівнює три параметри елемента з описом у @font-face:

  1. font-family — збігається?
  2. font-weight — збігається?
  3. font-style — збігається?

Якщо всі три збіглися — завантажується відповідний файл шрифта.

Запасний шрифт (font stack)

body {
    font-family: "PT Sans", Arial, sans-serif;
}
Завжди вказуйте запасний шрифт: назва шрифта → системний шрифт (Arial, Georgia) → загальне сімейство (sans-serif або serif).
Сімейство Опис Приклад
sans-serif Без засічок (гротеск) Arial, Helvetica
serif Із засічками (антиква) Times New Roman, Georgia

22. Зчитування параметрів тексту з макета

У Photoshop/Figma для кожного текстового шару зчитуємо:

Параметр CSS-властивість Примітка
Сімейство шрифта font-family PT Sans, Roboto тощо
Начертання (Bold, Regular…) font-weight 400 = Regular, 700 = Bold
Розмір шрифта font-size Переконайтесь, що одиниці — пікселі
Висота рядка line-height Якщо «Auto» → normal
Uppercase іконка text-transform: uppercase
Колір color Піпетка або панель властивостей шару
Однорядковий текст: не копіюйте line-height для заголовків в одну стрічку! Дизайнери часто використовують висоту рядка для відступів. Якщо текст стане дворядковим — міжрядковий інтервал буде занадто великим. Ставте line-height: normal або підберіть адекватне значення.

23. Формати зображень

Формат Тип Прозорість Стиснення Для чого
JPEG Растр Ні З втратою якості Фотографії, фони, ілюстрації
PNG Растр Так Без втрати якості Логотипи, елементи з прозорістю
SVG Вектор Так Мінімальний розмір Іконки, графіки, прості ілюстрації
WebP Растр Так Краще за JPEG/PNG Сучасна альтернатива JPEG та PNG
WebP — сучасний формат від Google. Підтримується усіма браузерами з 2020 року. Менший розмір файлу при тій самій якості.

24. Підсумкова таблиця

Тема Ключове
align-items Вирівнювання по додатковій осі: flex-start, center, flex-end, baseline, stretch
justify-content Вирівнювання по головній осі: center, space-between, space-around, space-evenly
flex-shrink Коефіцієнт стиснення: 1 (за замовчуванням) — стискається, 0 — ні
flex-grow Коефіцієнт розтягування: 0 (за замовчуванням), 1+ — займає вільний простір
flex-basis Початковий розмір елемента; пріоритетніша за width/height
flex (скорочений) flex: none — фіксований; flex: 1 — займає простір; flex: auto — розтягується за вмістом
Розподіл простору Числа flex визначають пропорції: flex: 2 + flex: 1 = 2/3 + 1/3
order Зміна порядку відображення без зміни HTML; менше число — раніше
align-content Вирівнювання рядків у багаторядковому flex-контейнері (flex-wrap: wrap)
align-self Індивідуальне вирівнювання flex-елемента; перевизначає align-items контейнера
margin: auto у flex Центрує елемент і по горизонталі, і по вертикалі; керує окремими елементами
position: fixed Як absolute, але фіксується при прокрутці; завжди відносно viewport
display: none Повне приховування; елемент «не існує» (не займає місце, не інтерактивний)
Popup-паттерн .popup (display: none) + .popup--active (display: flex); JS додає/видаляє клас
Специфічність 4 числа: inline / id / класи+псевдокласи / теги+псевдоелементи
Однакова специфічність Перемагає правило, що стоїть нижче в CSS
!important Підвищує пріоритет однієї властивості; антипатерн, уникайте
Селектор > Дочірній (перший рівень); не впливає на специфічність
@font-face Описує файл шрифта; один @font-face = одне начертання
font stack Завжди: кастомний → системний → sans-serif/serif
Формати зображень JPEG — фото; PNG — прозорість; SVG — іконки; WebP — сучасна альтернатива
🔍
Почніть вводити назву лекції або тему