🕐 12 хв читання

Верстка адаптивного макета

Конспект лекції: кросбраузерність, 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? 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 використовує систему containerrowcol:

<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 — плавна прокрутка до якорів
🔍
Почніть вводити назву лекції або тему