Skip to main content

Що таке адаптивний веб-дизайн

Адаптивний веб-дизайн (responsive web design, RWD) - підхід, при якому сайт автоматично підлаштовує розмітку і контент під розмір екрана: від 320px мобільного до 2560px монітора.

Теорія

TL;DR

  • Три складові RWD: рідинні сітки (%), гнучкі зображення (max-width: 100%), медіа-запити (@media)
  • Фіксована розмітка в пікселях ламається на мобільному; RWD перебудовується без горизонтального скролу
  • Мета-тег viewport обов'язковий: без нього мобільний браузер припускає ширину 980px
  • Mobile-first: базовий CSS для маленьких екранів, а @media (min-width) додає стилі для більших
  • RWD за замовчуванням для будь-якого сайту; фіксована ширина виправдана хіба що для кіоск-застосунку

Швидкий приклад

html
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> /* Мобільний: блок займає 90% екрана */ .box { width: 90%; margin: 20px auto; } img { max-width: 100%; height: auto; } /* Планшет і більше: 50% */ @media (min-width: 768px) { .box { width: 50%; } } </style> </head> <body> <div class="box">Контент перебудовується під кожен екран.</div> </body> </html>

На телефоні блок займає ~90% viewport. На планшеті звужується до 50%. Зображення ніколи не виходить за межі контейнера.

Головна відмінність

Фіксований макет задає ширину в пікселях. На телефоні з 375px екраном колонка width: 960px виходить за межі viewport і з'являється горизонтальний скрол. RWD використовує %, vw і fr, тому елементи займають рівно стільки місця, скільки є. Браузер перераховує модель блоку при кожній зміні розміру і перебудовує контент.

Mobile-first проти desktop-first

Mobile-first означає: базові стилі для найменшого екрана, а min-width брейкпоінти додають ускладнення для більших. Desktop-first робить навпаки через max-width. Mobile-first краще: телефон отримує менше CSS, не завантажує десктопні стилі на повільному з'єднанні, і підхід змушує думати про контент з самого початку.

css
/* Mobile-first: одна колонка за замовчуванням */ .card-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; } /* Планшет: дві колонки */ @media (min-width: 768px) { .card-grid { grid-template-columns: repeat(2, 1fr); } } /* Десктоп: чотири колонки */ @media (min-width: 1200px) { .card-grid { grid-template-columns: repeat(4, 1fr); } }

Коли застосовувати

  • Новий сайт або редизайн: RWD за замовчуванням
  • Документаційний сайт із великою кількістю контенту: RWD з mobile-first медіа-запитами
  • Кіоск-застосунок для одного пристрою: фіксована ширина прийнятна
  • Швидкий фікс для legacy-сайту: додати медіа-запити поверх існуючого CSS
  • Сторінка з вимогами до продуктивності на слабких пристроях: RWD з ледачим завантаженням зображень

Як браузер це обробляє

Браузер парсить HTML і CSS у дерево рендерингу. CSSOM застосовує медіа-запити на етапі розрахунку стилів, а Blink (рушій Chrome) перераховує ширину, висоту і відступи з відносними одиницями. Мета-тег viewport каже браузеру використовувати реальну ширину пристрою замість стандартних 980px.

Типові помилки

Відсутній мета-тег viewport

html
<!-- Неправильно: мобільний браузер масштабує сторінку як 980px десктоп --> <div style="width: 960px;">Контент виходить за межі</div>

Додай <meta name="viewport" content="width=device-width, initial-scale=1"> на кожну HTML-сторінку. Без нього медіа-запити на мобільних не спрацюють, бо браузер вважає ширину viewport рівною 980px. Це перше, що перевіряють, коли мобільні стилі зненацька перестають працювати.

Фіксована висота в сітці на відносних одиницях

css
/* Неправильно: ламається при повороті або великому контенті */ .row { height: 500px; } /* Правильно */ .row { min-height: 100vh; }

Відсоткова висота вимагає визначеної висоти батька. На телефоні після повороту height: 500px обрізає контент. Використовуй min-height або flexbox з align-items: stretch.

Desktop-first медіа-запити з важкими ресурсами

css
/* Неправильно: телефон завантажує зображення навіть якщо sidebar прихований */ .sidebar { background: url('large-image.jpg'); } @media (max-width: 768px) { .sidebar { display: none; } }

Телефон все одно завантажує large-image.jpg. Переверни логіку: базовий стан для мобільного, додаткові стилі через min-width.

Зображення без max-width

css
/* Неправильно: зображення 800px виходить за межі 375px екрана */ img { width: 800px; } /* Правильно */ img { max-width: 100%; height: auto; }

nav шириною 100vw

css
/* Неправильно: vw включає ширину смуги прокрутки у старих Chrome */ nav { width: 100vw; } /* Правильно */ nav { width: 100%; }

Смуга прокрутки зміщує розмітку. Саме цей vw-баг частіше за інші провокує зсуви в продакшені. width: 100% - безпечніший варіант.

Де зустрічається в реальних проектах

  • Bootstrap 5: container-fluid з адаптивною сіткою, використовується приблизно на 40% топових сайтів
  • Tailwind CSS: класи sm:, md:, lg: автоматично додають медіа-запити
  • CSS Grid: repeat(auto-fit, minmax(250px, 1fr)) для колонок без медіа-запитів
  • WordPress Gutenberg: container queries для попереднього перегляду в редакторі блоків
  • GitHub і Netflix: карткові сітки з переходом від 1 до 4 колонок на тих самих брейкпоінтах

Питання на співбесіді

Q: Яка різниця між media queries і container queries?
A: Media queries перевіряють розмір viewport. Container queries перевіряють розмір батьківського елемента. Container queries зручніші для повторно використовуваних компонентів, наприклад карток, що з'являються в різних контекстах.

Q: Як працює мета-тег viewport?
A: Він каже браузеру рендерити сторінку в реальній ширині пристрою, а не в стандартних 980px. Без нього @media (max-width: 768px) на більшості телефонів не спрацює.

Q: Які одиниці краще для адаптивних макетів?
A: % і fr для колонок сітки, rem для розмірів шрифтів, vw/vh для повноекранних секцій. Уникай px для ширин у рідинних макетах.

Q: Як тестувати адаптивний дизайн?
A: DevTools Chrome з емуляцією пристроїв для швидких перевірок. Для продакшену - реальні пристрої. Lighthouse покаже проблеми з продуктивністю через неоптимізовані зображення.

Q (senior): Компонент картки використовується в 3-колонковій сітці і у вузькому сайдбарі. Чому container queries вирішують тут проблему, яку media queries не можуть?
A: Media query спрацьовує при фіксованій ширині viewport незалежно від того, де знаходиться картка. Container query спрацьовує залежно від ширини батьківського контейнера. Одна і та сама картка отримає горизонтальний макет у широкій сітці і вертикальний у вузькому сайдбарі без додаткового CSS або JavaScript.

Приклади

Базовий: адаптивна карткова сітка

css
/* Мобільний: одна колонка */ .card-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; padding: 1rem; } /* Планшет: дві колонки */ @media (min-width: 768px) { .card-grid { grid-template-columns: repeat(2, 1fr); } } /* Десктоп: чотири колонки */ @media (min-width: 1200px) { .card-grid { grid-template-columns: repeat(4, 1fr); } } .card { border: 1px solid #ddd; padding: 1rem; }

На телефоні одна картка в рядку, на планшеті дві, на десктопі чотири. Два брейкпоінти, ніякого JavaScript. Саме такий патерн використовує GitHub для карток репозиторіїв.

Середній рівень: автоматичне перебудування без медіа-запитів

css
.grid { display: grid; /* Стільки колонок, скільки вміщає контейнер, кожна мінімум 250px */ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; }

auto-fit створює стільки колонок, скільки вміщає контейнер. Коли viewport звужується нижче ~500px, сітка автоматично переходить на одну колонку. Медіа-запити не потрібні. Такий підхід використовується в прикладах MDN і більшості сучасних бібліотек компонентів.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?