Чому медіа-запити потрібні в CSS
Медіа-запити (media queries) - це CSS-правила, які застосовують стилі залежно від характеристик пристрою: ширини екрану, орієнтації або кольорової схеми.
Теорія
TL;DR
- Медіа-запити як офіціант, що подає різні порції залежно від столика: та сама страва, але розмір підлаштовується під потреби. Базові стилі для всіх, окремі правила для вузьких екранів.
- Без них один CSS-файл нав'язує однаковий макет усім пристроям. Три колонки на 1440px перетворюються на нечитабельну кашу на 375px телефоні.
max-width- для desktop-first,min-width- для mobile-first (рекомендований підхід).- Спрацьовують миттєво при зміні розміру вікна, без JavaScript.
Швидкий приклад
/* Базово: 3 колонки на десктопі */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
/* Телефон: екран вужчий за 600px → одна колонка */
@media (max-width: 600px) {
.card-grid {
grid-template-columns: 1fr; /* картки складаються вертикально, без горизонтального скролу */
}
}На десктопі три картки стоять поряд. На iPhone 375px вони складаються в один стовпець автоматично.
Чому фіксовані стилі не працюють
CSS без медіа-запитів фіксує один макет для всіх пристроїв. Браузер обирає один набір правил і застосовує його всюди, незалежно від розміру екрану. Медіа-запити дозволяють браузеру перевірити реальний viewport під час рендерингу і активувати тільки ті блоки правил, які підходять. Один файл стилів, різна поведінка на кожному пристрої.
Коли використовувати
- Mobile-first: базові стилі для мобільних, потім
@media (min-width: 768px)для ширших екранів. - Стилі для друку:
@media print { .no-print { display: none; } }прибирає навігацію зі сторінки при друці. - Темна тема:
@media (prefers-color-scheme: dark) { body { background: #000; } }. - Орієнтація:
@media (orientation: landscape) { video { height: 100vh; } }. - Доступність:
@media (prefers-reduced-motion: reduce) { * { animation: none; } }.
Як браузер це обробляє
Браузери парсять весь CSS наперед. Під час рендерингу рушій (Blink у Chrome, Gecko у Firefox) перевіряє кожну медіа-характеристику відносно поточного viewport через window.matchMedia(). При зміні розміру вікна відповідні набори правил активуються миттєво. Жодного перезавантаження сторінки, жодного перерахунку для елементів поза активними правилами.
Типові помилки
width замість min-width або max-width:
/* Неправильно: спрацює лише на точно 768px */
@media (width: 768px) { ... }
/* Правильно: спрацює для 768px і менше */
@media (max-width: 768px) { ... }Desktop-first база з мобільним як другорядним:
/* Неправильно: мобільний успадковує 3 колонки, якщо override відсутній */
.grid { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 768px) { .grid { grid-template-columns: 1fr; } }
/* Правильно: mobile-first, складніші стилі додаються для ширших екранів */
.grid { grid-template-columns: 1fr; }
@media (min-width: 769px) { .grid { grid-template-columns: repeat(3, 1fr); } }Вкладені медіа-запити (одна з найпоширеніших CSS-помилок на Stack Overflow):
/* Неправильно: браузер повністю ігнорує внутрішній запит */
@media (max-width: 768px) {
.parent {
@media (max-width: 480px) { .child {} }
}
}
/* Правильно: обидва запити окремо */
@media (max-width: 480px) { .child {} }Я бачив, як розробники годинами шукали причину, чому макет ламається на телефоні, і зрештою виявляли, що вкладений запит просто ігнорувався весь цей час.
Де зустрічається в реальних проектах
- Tailwind CSS: брейкпоінти
md:генерують@media (min-width: 768px)автоматично. - Bootstrap 5: використовує
@media (min-width: 576px)для налаштування ширини.container. - React-застосунки:
@media (max-width: 1024px) { .menu-toggle { display: block; } }для бургер-меню. - Next.js 14: глобальний CSS з медіа-запитами для адаптивного макету на рівні сторінки.
Питання на співбесіді
Q: У чому різниця між @media (max-width: 768px) і viewport-одиницями типу vw?
A: max-width перемикає цілі набори правил на конкретному брейкпоінті. vw масштабує одну властивість безперервно, наприклад font-size: 5vw. Медіа-запити дають дискретні зміни макету, viewport-одиниці дають плавне масштабування.
Q: Як реалізувати темну тему через CSS?
A: @media (prefers-color-scheme: dark) { body { background: #000; color: #fff; } }. Браузер зчитує налаштування OS і застосовує стилі автоматично, JavaScript не потрібен.
Q: Що таке container queries і чим вони відрізняються від media queries?
A: Медіа-запити реагують на розмір viewport. Container queries (@container) реагують на розмір батьківського елемента, що робить компоненти перевикористовуваними незалежно від місця розміщення. Підтримуються в Chrome 105+ і Firefox 110+.
Q: Як дебажити медіа-запит, що не спрацьовує в iOS Safari?
A: Спочатку перевір viewport meta-тег: <meta name="viewport" content="width=device-width, initial-scale=1">. Без нього iOS рендерить у десктопному масштабі і брейкпоінти поводяться непередбачувано. Також перевір -webkit- префікси для специфічних властивостей.
Приклади
Базовий: відступи залежно від розміру екрану
.hero {
padding: 100px 40px; /* десктоп: багато повітря */
}
@media (max-width: 768px) {
.hero {
padding: 20px 10px; /* мобільний: компактно */
}
}На 1920px моніторі отримуємо 100px відступ зверху і знизу. На iPhone 375px він падає до 20px. Той самий елемент, дві поведінки, нуль JavaScript.
Колапс навігації на планшеті і мобільному
.nav-bar {
display: flex;
justify-content: space-between; /* горизонтально на десктопі */
}
.menu-toggle {
display: none; /* бургер схований на десктопі */
}
@media (max-width: 1024px) {
.nav-bar {
flex-direction: column; /* стекається вертикально для менших екранів */
}
.menu-toggle {
display: block; /* з'являється іконка бургера */
}
}Цей патерн є в кожному продакшн-застосунку з адаптивною навігацією. Кнопка-бургер з'являється лише тоді, коли екран занадто вузький для горизонтальної панелі. CSS повністю контролює зміну макету.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.