🕐 7 хв читання

Верстка гумового макета

Конспект лекції: фіксована, гумова та адаптивна верстка, відносні одиниці, відсоткові розміри

1. Фіксована, гумова та адаптивна верстка

Існує три основних підходи до верстки:

Підхід Одиниці Поведінка
Фіксована Пікселі (px) Розміри жорстко задані. При зменшенні вікна з'являється горизонтальна прокрутка
Гумова (fluid) Відсотки (%) Елементи пропорційно змінюють розмір разом із батьківським блоком, але залишаються на своїх місцях
Адаптивна (responsive) % + медіазапити На певній точці елементи змінюють розташування (наприклад, дві колонки стають однією)
На практиці гумова та адаптивна верстка завжди використовуються разом: у певному діапазоні працює «гума», а коли місця залишається занадто мало — спрацьовує медіазапит і змінюється розкладка.

Більше 60–80 % користувачів сучасних сайтів заходять з мобільних пристроїв, тому адаптивність — обов'язкова вимога.

2. Ширина у відсотках

Ширина у відсотках розраховується від ширини батьківського елемента.

/* Фіксована верстка */
.container { width: 1000px; }
.content  { width: 650px; }
.sidebar  { width: 350px; }

/* Гумова верстка */
.content  { width: 65%; }
.sidebar  { width: 35%; }

Блочний елемент за замовчуванням займає 100 % доступної ширини, тому батьківському контейнеру width: 100% можна не задавати.

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

3. Висота у відсотках

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

/* Не працює — висота батька auto */
.parent { }
.child  { height: 50%; } /* ігнорується */

/* Працює — висота батька задана явно */
.parent { height: 400px; }
.child  { height: 50%; } /* = 200px */
Чому для ширини не потрібна явна ширина батька? Браузер завжди знає ширину — вона обмежена шириною вікна. А висота за замовчуванням auto і визначається контентом, тому відсоток від auto браузер обчислити не може.

Фіксувати висоту для блоків з динамічним контентом — погана практика: якщо контенту більше, він виллється за межі блоку.

4. Відсотки для position: absolute і fixed

Для абсолютно позиціонованих елементів розміри у відсотках беруться не від прямого батька, а від найближчого предка з position: relative (контексту позиціонування).

.wrapper {
    position: relative;
    width: 500px;
    height: 300px;
}

.parent {
    width: 100px;
    height: 100px;
}

.child {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;  /* = 500px (від wrapper) */
    height: 100%; /* = 300px (від wrapper) */
}

Для position: fixed розміри завжди беруться від viewport — вікна браузера. width: 100% = вся ширина екрана, height: 100% = вся висота екрана.

5. max-width і min-width

Коли ширина задана у відсотках або не обмежена — на широких екранах блок розтягується занадто сильно: текст стає важко читати, зображення надмірно обрізаються.

.container {
    width: 100%;
    max-width: 1280px;
    margin-left: auto;
    margin-right: auto;
}
Властивість Що робить
max-width Обмежує максимальну ширину. Блок «гумовий», але ніколи не стане ширшим за вказане значення
min-width Обмежує мінімальну ширину. Якщо екран вужчий — з'являється горизонтальна прокрутка
Важливо: при використанні max-width обов'язково додайте margin-left: auto і margin-right: auto, щоб центрувати блок. Інакше він притиснеться до лівого краю.

min-width — це тимчасове рішення: воно не позбавляє горизонтальної прокрутки. Для коректного відображення на вузьких екранах потрібна адаптивна верстка з медіазапитами.

6. margin-left: auto та margin-right: auto — запис

Для центрування блоку краще писати розгорнуті властивості замість скороченого запису:

/* Скорочений запис — задає зайві margin-top і margin-bottom */
.container { margin: 0 auto; }

/* Розгорнутий запис — задає лише потрібне */
.container {
    margin-left: auto;
    margin-right: auto;
}

Проблема скороченого запису: margin: 0 auto обнулює margin-top і margin-bottom. Якщо десь вище у CSS ви задали вертикальні відступи — вони будуть перезаписані. З розгорнутими властивостями цього конфлікту не буде.

7. margin і padding у відсотках

Контрінтуїтивне правило: і горизонтальні, і вертикальні margin та padding у відсотках розраховуються від ширини батьківського елемента.

.wrapper { width: 1000px; }
.card {
    margin: 1%;   /* top, right, bottom, left — усі = 10px */
    padding: 1%;  /* top, right, bottom, left — усі = 10px */
}
Запам'ятайте: навіть margin-top, margin-bottom, padding-top, padding-bottom у відсотках беруться від ширини батька, а не від висоти. Це стандартна поведінка CSS.

На практиці відступи зазвичай задають у пікселях, тому ця особливість рідко створює проблеми. Але вона лежить в основі цікавої техніки — збереження пропорцій блоку.

8. Техніка збереження пропорцій блоку (padding-hack)

Оскільки padding-bottom у відсотках рахується від ширини батьківського елемента, ми можемо створити блок, який завжди зберігає свої пропорції:

.aspect-ratio-box {
    height: 0;
    padding-bottom: 100%; /* квадрат */
    overflow: hidden;
}

Принцип роботи:

  1. height: 0 — висота контенту не впливає на розмір блоку
  2. padding-bottom: 100% — висота блоку дорівнює його ширині (бо padding рахується від ширини батька)
  3. overflow: hidden — обрізає контент, що виходить за межі

Значення padding-bottom для різних пропорцій:

Пропорція padding-bottom
1:1 (квадрат) 100%
16:9 (відео) 56.25%
4:3 75%
3:2 66.66%

9. Вбудовування відео з YouTube (реальний приклад)

Найпоширеніший випадок застосування padding-hack — створення гумового контейнера для вбудованого відео:

<!-- HTML -->
<div class="video-wrapper">
    <iframe src="https://www.youtube.com/embed/VIDEO_ID"
            allowfullscreen></iframe>
</div>
/* CSS */
.video-wrapper {
    position: relative;
    height: 0;
    padding-bottom: 56.25%; /* 16:9 */
    overflow: hidden;
}

.video-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

Як це працює:

  1. iframe з position: absolute не впливає на висоту батька
  2. Висота .video-wrapper визначається лише padding-bottom
  3. iframe розтягується на 100 % ширини та висоти обгортки
  4. При зміні ширини екрана відео зберігає пропорції 16:9
Сучасна альтернатива: у CSS є властивість aspect-ratio, яка вирішує цю задачу елегантніше: aspect-ratio: 16 / 9. Підтримується всіма сучасними браузерами (Chrome 88+, Firefox 89+, Safari 15+). Але padding-hack досі зустрічається у старих проєктах.

10. font-size у відсотках

Розмір шрифту у відсотках рахується від font-size батьківського елемента:

.parent { font-size: 20px; }
.child  { font-size: 50%; }  /* = 10px */

Практичний приклад: кнопка <button>

Елемент <button> має дефолтний font-size: 13.333px, який не наслідується від батька. Щоб розмір тексту кнопки збігався з розміром тексту контейнера:

button {
    font-size: 100%; /* наслідує розмір від батьківського елемента */
}

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

11. Flexbox: повторення ключових концепцій

Дві осі

У Flexbox є головна (main) і додаткова (cross) осі. Замість «ліворуч/праворуч» коректно казати «початок/кінець осі».

Висота елементів у рядку

За замовчуванням flex-елементи у рядку розтягуються на однакову висоту — це поведінка align-items: stretch. Колонки однакової висоти — це дефолтна поведінка Flexbox, не потрібно нічого додатково налаштовувати.

Зміна напрямку додаткової осі

Напрямок додаткової осі можна змінити двома способами:

Спосіб Пояснення
flex-direction: column Головна ось стає вертикальною → додаткова стає горизонтальною
flex-wrap: wrap-reverse Елементи переносяться у зворотному напрямку → додаткова ось змінює напрямок

12. Flexbox замість float

Float для створення колонок — застарілий підхід. Всі сучасні браузери повноцінно підтримують Flexbox.

Flexbox автоматично скасовує float

.news-item {
    float: left; /* старий підхід для колонок */
}

.news {
    display: flex; /* float автоматично перестає працювати */
}

Якщо для батьківського елемента задано display: flex, то float дочірніх елементів ігнорується. Це закладено в специфікацію Flexbox.

Проблеми float, які вирішує Flexbox

  • Батьківський блок «втрачає» висоту (потрібен clearfix-хак)
  • Складніше керувати вирівнюванням та розподілом простору
  • Потрібні додаткові хаки для однакової висоти колонок
Правило: якщо бачите float, який використовується для колонок — сміливо замінюйте на display: flex. Залишайте float лише для його початкового призначення — обтікання зображень текстом.

13. Clearfix — хак для float (історична довідка)

Коли float використовувався для колонок, батьківський блок «схлопувався» — не враховував висоту float-елементів. Для виправлення застосовували clearfix:

.clearfix::after {
    content: "";
    display: table;
    clear: both;
}

У сучасній верстці з Flexbox clearfix не потрібен — це повністю застарілий прийом.

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

Властивість Від чого рахуються % Примітка
width Ширина батьківського елемента Працює завжди
height Висота батьківського елемента Тільки якщо висота батька задана явно
margin (всі сторони) Ширина батьківського елемента Навіть вертикальні — від ширини!
padding (всі сторони) Ширина батьківського елемента Навіть вертикальні — від ширини!
font-size font-size батьківського елемента Є кращі одиниці (em, rem)
width / height при position: absolute Розміри найближчого предка з position: relative Не від прямого батька!
width / height при position: fixed Розміри viewport (вікна браузера) Завжди від вікна
🔍
Почніть вводити назву лекції або тему