Верстка адаптивного макета
Конспект лекції: кросбраузерність, caniuse.com, вендорні префікси, стратегії адаптивної верстки
1. Кросбраузерність та caniuse.com
Кросбраузерність — це здатність сайту коректно відображатись у різних браузерах. Це одна з найпоширеніших проблем верстальників.
Сервіс caniuse.com дозволяє перевірити підтримку будь-якої CSS/HTML/JS технології у сучасних браузерах. Ви вводите назву технології та бачите повну розкладку підтримки по версіях браузерів.
Приклади використання:
- Перевірка підтримки CSS Custom Properties (змінних)
- Перевірка підтримки
-webkit-line-clamp - Перевірка підтримки тега
<picture> - Перевірка нових CSS/JS можливостей
2. Вендорні префікси
Вендорні префікси — це спеціальні приставки до CSS-властивостей, які браузери використовували для експериментальних можливостей:
-webkit-— Chrome, Safari, новіші версії Opera-moz-— Firefox-o-— старі версії Opera-ms-— Internet Explorer, Edge (старіший)
Спочатку ці префікси створювались для демонстрації майбутніх можливостей. Згодом розробники почали використовувати їх як повноцінні властивості, що призвело до проблем із сумісністю.
Приклад властивості з вендорним префіксом:
.element {
-webkit-line-clamp: 3;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
}
Сьогодні більшість властивостей підтримуються без префіксів. Перевіряйте актуальність на caniuse.com.
3. Обрізка тексту: text-overflow та line-clamp
Однорядкова обрізка з трикрапкою
Для обрізки тексту в одну строку з трикрапкою потрібна комбінація трьох властивостей:
.truncate {
white-space: nowrap; /* Забороняємо перенос */
overflow: hidden; /* Ховаємо зайве */
text-overflow: ellipsis; /* Додаємо трикрапку */
}
Усі три властивості обов'язкові — без будь-якої з них ефект не працюватиме.
Багаторядкова обрізка з -webkit-line-clamp
Для обрізки після певної кількості рядків використовується -webkit-line-clamp:
.multiline-truncate {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; /* Кількість рядків */
overflow: hidden;
}
Незважаючи на префікс -webkit-, ця властивість працює у всіх сучасних браузерах.
4. BrowserHacks (CSS-хаки)
BrowserHacks — це збірник CSS/JS-костилів для визначення конкретного браузера або його версії. Це спеціальні конструкції без логічного сенсу, які працюють тільки в певних браузерах.
Приклад хака для визначення Chrome:
/* Спрацює тільки в Chrome */
@media screen and (-webkit-min-device-pixel-ratio: 0) {
.element {
color: red;
}
}
Використовувати хаки не рекомендується — це свідчить про низьку якість верстки. Якщо все ж доводиться, обов'язково залишайте коментарі в коді.
5. Типи верстки: адаптивна, відгукова, гумова
Гумова верстка (Fluid/Liquid)
Сайт розтягується разом з вікном браузера. Усі блоки мають відносні розміри (у відсотках). Приклад — Вікіпедія.
Проблема: на дуже широких екранах текст стає важко читати — рядки занадто довгі. Рішення:
- Обмежити максимальну ширину (
max-width) - Розбити текст на колонки (CSS
columns)
Адаптивна/Відгукова верстка (Responsive)
Сайт перебудовується при зміні ширини вікна за допомогою медіазапитів. Елементи змінюють розташування, розміри, видимість. Це найпоширеніший підхід.
overflow: hidden як костиль
Поширена помилка — замість пошуку причини горизонтальної прокрутки ставити overflow: hidden на
body. Це лише маскує проблему, а не вирішує її.
6. CSS-дебаг через outline
Швидкий спосіб візуалізувати розмітку для пошуку причин overflow або зсувів — додати обведення всім елементам:
Метод outline
/* Обведення всіх елементів — не впливає на розміри */
* {
outline: 1px solid red;
}
Метод напівпрозорого фону
/* Кожен вкладений рівень стає темнішим */
* {
background: rgb(0 0 0 / 0.1);
}
outline не впливає на розміри блоків і не зміщує
сусідні елементи — ви бачите реальну розкладку. border додає товщину і може змінити поведінку
верстки.
7. Практичний приклад: адаптивна картка користувача
Розглянемо верстку картки, яка на десктопі показує фото, ім'я, посаду та контакти вертикально, а на мобільному — фото на весь екран із накладеним текстом.
HTML-структура
<div class="card">
<img class="card__image"
src="photo.jpg"
alt="Фото">
<div class="card__info">
<h2 class="card__name">Jane Smith</h2>
<p class="card__post">Photographer</p>
<a class="card__contact" href="tel:+380501234567">+380 50 123 45 67</a>
<a class="card__contact" href="mailto:test@example.com">test@example.com</a>
</div>
</div>
Десктопна версія (object-fit: cover)
.card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
text-align: center;
background: blue;
color: white;
}
.card__image {
width: 100px;
height: 100px;
object-fit: cover; /* Зберігаємо пропорції */
border-radius: 50%; /* Коло */
border: 4px solid white;
}
Мобільна версія (шари з position і z-index)
.card {
position: relative;
}
.card__image {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 1;
}
.card__info {
position: relative;
z-index: 2;
background: rgba(0, 0, 255, 0.5); /* Напівпрозорий фон */
}
Ключовий прийом: зображення розтягується на весь блок через position: absolute, а текстовий блок
із z-index вищим накладається зверху з напівпрозорим фоном.
8. CSS-трикутники через border
Коли елемент має нульову ширину та висоту, а рамки — великий розмір, кожна з чотирьох рамок утворює трикутник:
.triangle {
width: 0;
height: 0;
border-width: 100px;
border-style: solid;
border-color: red green blue black;
}
Щоб залишити один трикутник, робимо решту рамок прозорими:
/* Трикутник вправо */
.triangle-right {
width: 0;
height: 0;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-left: 100px solid green;
border-right: 0;
}
Трикутники використовуються для стрілок випадаючих меню, підказок (tooltips), складових фігур (трапецій тощо). Технологія проста та не потребує зображень.
9. Pill shape через border-radius
Кнопка-«пігулка» (pill) — елемент із повністю заокругленими краями. Поширена помилка — використовувати
border-radius: 50%, що перетворює прямокутник на овал.
/* Проблема: 50% робить овал, а не пігулку */
.oval {
border-radius: 50%; /* Овальна форма */
}
/* Рішення: велике значення створює ідеальні заокруглення */
.pill {
border-radius: 100vw; /* Завжди ідеальна пігулка */
}
Значення 100vw свідомо більше за будь-який можливий радіус — браузер автоматично обмежить його
до половини найменшого виміру елемента. Результат — ідеальні заокруглені краї незалежно від ширини чи висоти.
Варіації форми
/* Купол (заокруглення тільки зверху) */
.dome {
border-radius: 100vw 100vw 0 0;
}
10. Логічні оператори в медіазапитах
Кома (OR — логічне АБО)
Об'єднує кілька незалежних медіазапитів. Стилі застосовуються, якщо хоча б один з них справджується:
@media (max-width: 600px), (orientation: portrait) {
/* Спрацює при ширині до 600px АБО при портретній орієнтації */
}
and (логічне І)
Об'єднує умови — стилі застосовуються тільки коли всі умови справджуються одночасно:
@media (min-width: 768px) and (max-width: 1024px) {
/* Тільки для ширин від 768px до 1024px */
}
not (логічне НЕ)
Заперечення — стилі застосовуються для всіх випадків, крім вказаного:
@media not print {
/* Для всіх пристроїв, крім друку */
}
На практиці підходу Mobile First із min-width зазвичай достатньо. Логічні оператори рідко
потрібні, але корисно знати про їхнє існування.
11. Повноекранний фон: background-size: cover
Для створення повноекранного блоку з фоновим зображенням використовується комбінація:
.hero {
height: 100vh; /* Вся висота вікна */
background-image: url('hero.jpg');
background-size: cover; /* Заповнює весь блок */
background-position: center;
background-repeat: no-repeat;
}
cover гарантує, що зображення заповнить весь блок без спотворень, обрізаючи зайве.
contain натомість вмістить усе зображення, але можуть залишитися порожні смуги.
Для адаптивних мобільних версій краще використовувати тег <picture>, який дозволяє
підвантажувати різні зображення для різних розмірів екрану.
12. 100vh для повноекранних секцій
Для створення блоку на всю висоту вікна використовують одиницю vh:
.fullscreen-section {
height: 100vh; /* 100% висоти viewport */
}
Проблема 100vh на мобільних пристроях
На мобільних браузерах є адресний рядок та панель навігації, які можуть ховатися при скролі. Класичне значення 100vh завжди дорівнює висоті вікна без урахування цих панелей — тобто це найбільша можлива висота viewport. Через це на мобільних 100vh може бути більшим за видиму область, і контент виходить за межі екрана.
Нові viewport-одиниці: svh, lvh, dvh
Для вирішення цієї проблеми у CSS з'явилися три нові одиниці висоти viewport:
| Одиниця | Назва | Що означає |
|---|---|---|
svh |
Small Viewport Height | Висота viewport, коли всі панелі браузера показані (найменша видима область) |
lvh |
Large Viewport Height | Висота viewport, коли всі панелі браузера приховані (найбільша видима область) |
dvh |
Dynamic Viewport Height | Динамічно змінюється при появі/зникненні панелей браузера |
vh на мобільних браузерах поводиться як lvh — завжди дорівнює найбільшому розміру viewport.
Як обрати правильну одиницю
dvh— найкращий вибір для повноекранних секцій (hero-блоки, лендінги). Контент завжди точно вписується у видиму область, навіть коли адресний рядок показанийsvh— гарантує, що контент ніколи не буде обрізаний, навіть при максимально видимих панелях. Корисно для елементів, де обрізання критичне (наприклад, форма входу або CTA-кнопка)lvh— поведінка ідентична класичномуvh. Рідко потрібний окремо, але може бути корисний, якщо ви свідомо хочете використати максимальну висоту
Приклад використання
/* Hero-блок, який завжди займає весь видимий екран */
.hero {
min-height: 100dvh;
}
/* Fallback для старих браузерів */
.hero {
min-height: 100vh; /* Старі браузери */
min-height: 100dvh; /* Сучасні браузери */
}
dvh динамічно змінюється при скролі, коли панелі браузера ховаються. Це може спричиняти небажане перемальовування (reflow) елементів. Тому для анімацій та фіксованих елементів краще використовувати svh або lvh, які мають стабільне значення.
Аналогічні одиниці для ширини
Ті самі варіанти існують і для ширини viewport: svw, lvw, dvw. Також є діагональні одиниці svi, lvi, dvi (inline) та svb, lvb, dvb (block), які враховують напрямок тексту. На практиці для ширини ці одиниці потрібні рідко, оскільки панелі браузера зазвичай впливають тільки на висоту.
13. Модульна сітка
Модульна сітка — це розбиття простору на рівні колонки, відносно яких розміщується контент. Ця концепція прийшла з типографіки (газети, журнали, енциклопедії).
Стандарт — 12 колонок, бо число 12 ділиться на 2, 3, 4 і 6:
| Поділ | Модулі | Відсотки |
|---|---|---|
| На 2 частини | 6 + 6 | 50% + 50% |
| На 3 частини | 4 + 4 + 4 | 33.33% + 33.33% + 33.33% |
| На 4 частини | 3 + 3 + 3 + 3 | 25% + 25% + 25% + 25% |
| Бічна панель + контент | 3 + 9 | 25% + 75% |
| Контент + бічна панель | 8 + 4 | 66.67% + 33.33% |
Переваги модульної сітки:
- Простіше вирівнювати елементи — думаємо модулями, а не пікселями
- Відсотки стають зрозумілими: 6 з 12 = 50%, 4 з 12 = 33.33%
- Дизайнеру та верстальнику легше спілкуватися
14. Bootstrap: сітка та компоненти
Фреймворк vs бібліотека
Фреймворк (Bootstrap) — це комплексне рішення: сітка, компоненти (кнопки, модальні вікна, каруселі, акордеони тощо). Бібліотека (FlexboxGrid) — вирішує одну задачу (наприклад, тільки сітку).
Підключення Bootstrap
<!-- CSS -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
<!-- JS (для інтерактивних компонентів) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js"></script>
Контейнер (container)
Клас container створює центровану колонку з фіксованою шириною для кожної точки злому:
| Ширина вікна | Ширина контейнера |
|---|---|
| < 576px | 100% |
| ≥ 576px | 540px |
| ≥ 768px | 720px |
| ≥ 992px | 960px |
| ≥ 1200px | 1140px |
| ≥ 1400px | 1320px |
Точки злому (Breakpoints)
| Префікс | Мінімальна ширина | Назва |
|---|---|---|
| (без префікса) | < 576px | Extra small |
sm |
≥ 576px | Small |
md |
≥ 768px | Medium |
lg |
≥ 992px | Large |
xl |
≥ 1200px | Extra large |
xxl |
≥ 1400px | Extra extra large |
Сітка (Grid System)
Bootstrap використовує систему container → row → col:
<div class="container">
<div class="row">
<div class="col-8">8 модулів з 12 (66.67%)</div>
<div class="col-4">4 модулі з 12 (33.33%)</div>
</div>
</div>
Адаптивні колонки
Додаючи префікс точки злому, задаємо різну кількість модулів для різних пристроїв:
<div class="row">
<!-- На sm і вище: 8 модулів, менше sm: 100% -->
<div class="col-sm-8">Основний контент</div>
<div class="col-sm-4">Бічна панель</div>
</div>
<div class="row">
<!-- Кілька точок злому одночасно -->
<div class="col-12 col-sm-8 col-md-6 col-lg-4">
Адаптивний блок
</div>
</div>
Коли використовувати Bootstrap
- Адміністративні панелі (де дизайн не принциповий)
- Швидке прототипування для показу клієнту
- Великі портали з повторюваними компонентами
- Проєкти, де більшість компонентів Bootstrap дійсно потрібні
15. FlexboxGrid
FlexboxGrid — це легка бібліотека, яка реалізує тільки модульну сітку на основі Flexbox. Класи практично
ідентичні Bootstrap: container, row, col.
Приклад використання:
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6 col-lg-4">
Контент
</div>
</div>
Підходить, коли потрібна лише сітка без компонентів. Для сучасних проєктів розгляньте також CSS Grid Layout як нативну альтернативу.
16. Правила найменування CSS-класів
Що НЕ варто робити
- Не називайте класи кольорами:
.red-button→ краще.button-dangerабо.button-primary. Колірна тема може змінитися - Не вказуйте теги в класах:
.div-header→ краще.header. Тег може змінитися - Не використовуйте порядкові номери:
.item-1,.item-2→ при додаванні нових елементів нумерація втрачає сенс - Не об'єднуйте незв'язані блоки:
.header, .footer, .sidebar { width: 100%; }→ тримайте стилі блоків окремо
Що ВАРТО робити
- Використовуйте семантичні назви:
.card__image,.nav__link - Один клас = один селектор: найкращий селектор — це один клас без вкладеності
- Дотримуйтесь єдиного стилю роздільників: якщо використовуєте дефіс — використовуйте скрізь, якщо camelCase — скрізь
- Методологія BEM: Block__Element--Modifier — перевірений підхід до іменування
- Переносьте логіку в HTML: замість
:nth-childкраще додати клас.item--first
Простота коду
Чим простіші ваші CSS-правила — тим легше іншим розробникам (і вам самим через час) розібратися в коді. Простий код також швидше обробляється браузером.
17. Спрощення класів-модифікаторів
Коли у вас є блок з кількома варіантами стилів (модифікаторами), зазвичай використовують базовий клас + клас-модифікатор:
<button class="btn btn-primary">Зберегти</button>
<button class="btn btn-danger">Видалити</button>
<button class="btn btn-outline">Скасувати</button>
Замість того щоб писати окремі стилі для кожного модифікатора, можна використати селектор [class|="btn"], який вибере всі елементи, де клас починається зі слова btn:
/* Базові стилі для всіх btn-* */
[class|="btn"] {
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
/* Конкретні модифікатори */
.btn-primary { background: #3b82f6; }
.btn-danger { background: #ef4444; }
.btn-outline { border: 1px solid currentColor; }
[class|="btn"] працює лише коли btn — перше слово в атрибуті class. Якщо елемент має class="card btn-primary", цей селектор його не вибере. Для таких випадків краще використовувати [class*="btn-"].
18. scroll-behavior: smooth
CSS-властивість для плавної прокрутки при переході за якірними посиланнями:
html {
scroll-behavior: smooth;
}
Після цього кліки на якірні посилання (наприклад, <a href="#section">) будуть плавно
прокручувати сторінку до потрібного елемента замість різкого стрибка.
19. Швидкість завантаження сайту
Формула швидкості завантаження:
Час = Кількість файлів × Об'єм файлів + Складність обробки
Як впливати на кожну складову:
- Кількість файлів: об'єднання CSS/JS-файлів, використання спрайтів/SVG замість окремих іконок
- Об'єм файлів: мініфікація, стиснення зображень, lazy loading
- Складність: простіші CSS-селектори, менше анімацій, Critical CSS
20. Підсумкова таблиця
| Тема | Ключове |
|---|---|
| caniuse.com | Перевірка підтримки технологій у браузерах |
| Вендорні префікси | -webkit-, -moz-, -o-, -ms- |
| text-overflow: ellipsis | + white-space: nowrap + overflow: hidden |
| -webkit-line-clamp | Багаторядкова обрізка з трикрапкою |
| Типи верстки | Гумова, адаптивна/відгукова |
| CSS-дебаг через outline | * { outline: 1px solid red; } — бачити межі всіх елементів |
| object-fit: cover | Заповнення блоку зображенням зі збереженням пропорцій |
| CSS-трикутники | border + width: 0 + height: 0 + transparent |
| Pill shape | border-radius: 100vw — ідеально закруглені кінці |
| Логічні оператори | Кома (OR), and (І), not (НЕ) |
| background-size: cover | Повноекранний фон без спотворень |
| 100vh / dvh / svh / lvh | Viewport-одиниці: класична, динамічна, мала, велика висота |
| Модульна сітка | 12 колонок, прийшла з типографіки |
| Bootstrap | Фреймворк: сітка + компоненти |
| FlexboxGrid | Бібліотека: тільки сітка |
| Найменування класів | Без кольорів, тегів, номерів; BEM; прості селектори |
| Класи-модифікатори | [class|="btn"] — спільні стилі для всіх btn-* |
| scroll-behavior | smooth — плавна прокрутка до якорів |