
📱 JavaScript: як визначити ширину екрана — аналог @media запитів у коді
Буває, верстка вже готова, CSS-медіазапити розставлені, а поведінку на конкретній контрольній точці потрібно відловити саме в JavaScript. Показати поп-ап тільки на мобільних, перебудувати сітку під час зміни розміру, запустити анімацію, коли екран «вузький», усе це вимагає від скрипту розуміння поточної ширини вікна.
Проблема в тому, що розробники часто йдуть складним шляхом: парсять window.innerWidth, вішають throttle на resize, порівнюють із магічними числами й отримують крихкий код, який живе окремо від CSS-контрольних точок. Але ж у браузері давно є метод, що працює з тими самими медіавиразами, що й CSS.
Нижче три практичні підходи: від сучасного matchMedia (працює як @media в CSS) до jQuery-варіанту для legacy-проєктів. З живими прикладами, які можна скопіювати та запустити просто зараз.
💡 Швидкий огляд:
matchMedia, нативний метод, що приймає CSS-медіавираз і повідомляє, чи виконується він просто зараз; ідеальний для синхронізації JS-логіки з CSS-контрольними точкамиresize+matchMedia, зв’язка, що реагує на зміну вікна браузера; скрипт дізнається про перетин контрольної точки миттєво, без періодичного опитуванняinnerWidth- jQuery-варіант, для проєктів, де jQuery вже на сторінці; той самий
resize, але без нативногоmatchMedia, порівняння йде через$(window).width()
MatchMedia, єдине джерело правди для ширини екрана
Головний недолік window.innerWidth, він нічого не знає про ваші CSS-контрольні точки. Ви ставите в медіазапитах 768px, а в JS пишете if (window.innerWidth < 768), і одного разу округлення або смуга прокрутки ламають синхронізацію.
window.matchMedia() розв’язує цю проблему радикально: він приймає той самий рядок медіавиразу, що й CSS-правило @media. Результат, об’єкт MediaQueryList із властивістю .matches (true / false). Жодних магічних чисел, жодного розходження з версткою.
Базовий синтаксис:
1 const mq = window.matchMedia("(min-width: 768px)"); 2 3 if (mq.matches) { 4 console.log("Планшет или шире — 768px+"); 5 } else { 6 console.log("Мобильное разрешение — меньше 768px"); 7 }
Той самий виклик matchMedia("(min-width: 768px)") браузер виконує за тими самими правилами, що й @media (min-width: 768px) у CSS. Якщо в CSS для цієї контрольної точки схований сайдбар, JS «бачить» те саме й може, наприклад, сховати мобільне меню.
Крім .matches, об’єкт MediaQueryList дає властивість .media (рядок вихідного запиту) і метод addEventListener для підписки на зміни. Це означає, що один раз оголосивши контрольну точку в конфігурації, ви можете використовувати її одночасно і в CSS, і в JS без дублювання магічних чисел, достатньо винести 768 у константу та підставляти в обидва місця.
Реакція на зміну розміру без throttle і милиць
Перевірка «зараз» — це пів справи. Справжня магія починається, коли скрипт дізнається про перетин контрольної точки в момент зміни вікна.
У MediaQueryList є подія change, вона спрацьовує рівно тоді, коли значення .matches перемикається. Не на кожен піксель зміни розміру, а лише під час переходу через межу:
1 const mq = window.matchMedia("(min-width: 500px)"); 2 3 mq.addEventListener("change", function (e) { 4 if (e.matches) { 5 console.log("Экран расширился до 500px или больше"); 6 } else { 7 console.log("Экран сузился меньше 500px"); 8 } 9 });
Для зворотної сумісності зі старими браузерами те саме можна зробити через загальний обробник resize на window:
1 window.addEventListener("resize", function () { 2 if (window.matchMedia("(min-width: 500px)").matches) { 3 console.log("Ширина экрана — минимум 500px"); 4 } else { 5 console.log("Меньше 500px"); 6 } 7 });

Різниця проста: change на MediaQueryList, подієво-чистий підхід (немає зайвих викликів під час зміни розміру всередині діапазону), а resize на window, fallback, зрозумілий будь-якому розробнику.
Діапазон ширини: між двома контрольними точками
Часте завдання, «від 769px до 1024px». matchMedia і тут працює як CSS: комбінуйте min-width і max-width в одному виразі:
1 window.addEventListener("resize", function () { 2 if ( 3 window.matchMedia("(min-width: 769px)").matches && 4 window.matchMedia("(max-width: 1024px)").matches 5 ) { 6 console.log("Планшетный диапазон: 769px – 1024px"); 7 } else { 8 console.log("За пределами планшетного диапазона"); 9 } 10 });
Або одним виразом (браузери розуміють складені медіазапити так само, як у CSS):
1 const tablet = window.matchMedia("(min-width: 769px) and (max-width: 1024px)"); 2 3 tablet.addEventListener("change", function (e) { 4 console.log(e.matches ? "Вошли в планшетный диапазон" : "Вышли из планшетного диапазона"); 5 });
Який варіант обрати? change на MediaQueryList, коли потрібно зловити саме момент перетину межі (наприклад, перебудувати DOM-дерево). resize + matchMedia, коли логіка простіша й потрібно просто «перевірити зараз» без підписки на майбутні переходи.
JQuery-варіант: коли matchMedia недоступний
Якщо проєкт на jQuery і поліфіли не варіант, той самий результат досягається порівнянням $(window).width() із пороговим значенням:
1 jQuery(document).ready(function ($) { 2 if ($(window).width() > 1000) { 3 console.log("Ширина экрана больше 1000px"); 4 } else { 5 console.log("Ширина экрана 1000px или меньше"); 6 } 7 });
Цей код виконується одноразово під час завантаження сторінки. Для відстеження зміни розміру обгорніть перевірку в обробник:
1 jQuery(document).ready(function ($) { 2 function checkWidth() { 3 if ($(window).width() > 1000) { 4 console.log("Ширина > 1000px"); 5 } else { 6 console.log("Ширина ≤ 1000px"); 7 } 8 } 9 10 checkWidth(); // первый запуск 11 $(window).on("resize", checkWidth); 12 });
Але пам’ятайте: $(window).width() і matchMedia можуть розійтися на кілька пікселів через смугу прокрутки. matchMedia працює з областю перегляду (viewport), так само, як CSS-правила. Тому для всього нового коду я рекомендую саме нативний метод.
MatchMedia проти innerWidth, коротко
Критерій |
|
|
|---|---|---|
Синхронізація з CSS | Повна (ті самі вирази) | Ручне підганяння чисел |
Подія під час перетину контрольної точки |
| Тільки |
Урахування смуги прокрутки | Як у CSS (viewport) | Залежить від браузера |
Виявлення темної теми / | Так (будь-який медіавираз) | Ні |
⁉️🤔 Часті запитання
Що краще: matchMedia чи window.innerWidth?
matchMediaкраще завжди, коли логіка прив’язана до CSS-контрольних точок. Він використовує ті самі правила, що й@media, виключено розходження на піксель-другий через смугу прокрутки або масштабування.innerWidthдоречний лише якщо потрібне точне числове значення (наприклад, для розрахунку кількості елементів, що вміщуються), а не факт «екран ширший за N пікселів».
Чи працює matchMedia у старих браузерах?
Так, підтримка широка: усі сучасні браузери, включно з мобільними, та Internet Explorer 10+. IE9 і нижче залишилися за бортом, для них доведеться використовувати
window.innerWidthабо jQuery-варіант зі статті. На практиці частка IE9 у 2026 році прямує до нуля.
Чи можна через matchMedia перевіряти не лише ширину?
Так, метод приймає будь-який валідний CSS-медіавираз. Наприклад:
(orientation: portrait), визначення орієнтації пристрою;(prefers-color-scheme: dark), темна тема в ОС;(prefers-reduced-motion: reduce), запит на вимкнення анімацій. Працює так само, як у CSS:window.matchMedia("(prefers-color-scheme: dark)").matchesповернеtrue, якщо в користувача ввімкнено темну тему.
Чи потрібно видаляти обробник change під час виходу зі сторінки?
У сучасному коді, ні. Браузер сам очищає пам’ять під час вивантаження сторінки. У SPA (React, Vue), де компонент монтується та розмонтовується без перезавантаження сторінки, обов’язково збережіть посилання на обробник і видаліть через
removeEventListenerуcomponentWillUnmount/onUnmounted, інакше отримаєте витік пам’яті та повторні спрацьовування на «мертвих» компонентах.
Чому $(window).width() і matchMedia іноді показують різну ширину?
Тому що вони вимірюють різне.
matchMediaпрацює з шириною viewport (область перегляду CSS), тією самою, яку використовують медіазапити.$(window).width()/window.innerWidthвключають ширину вертикальної смуги прокрутки, якщо вона є. Різниця зазвичай 15-17 px, якраз ширина скролбару. Звідси правило: прив’язуєте логіку до CSS-контрольних точок, використовуйтеmatchMedia; потрібна «чесна» ширина вікна в пікселях,innerWidth.
То що використовувати: підсумковий розклад
Для нового коду відповідь однозначна, window.matchMedia(). Він живе в одному контракті з вашим CSS, не вимагає ручного підганяння чисел під кожну контрольну точку й дає подієву модель «перемкнулося, дізнався» замість постійного опитування ширини.
Типовий сценарій, де різниця відчутна одразу: ви верстаєте картку товару, яка на десктопі показує галерею з чотирьох зображень, а на мобільному, одне, яке можна гортати. У CSS у вас @media (max-width: 768px), що змінює розкладку. У JS замість if (window.innerWidth <= 768) ви пишете matchMedia("(max-width: 768px)"), і браузер гарантує, що JS-умова спрацює рівно тоді ж, коли змінилася верстка. Жодних «майже потрапило», жодних багів на 767px через скролбар.
jQuery-підхід із $(window).width() залиште для підтримки старих проєктів, він працює, але змушує дублювати контрольні точки в коді й мовчки розходиться з CSS на ширину скролбару.
А якщо хочете побачити все вищеописане наживо, ось 10-хвилинний туторіал, де matchMedia розбирається від виклику до подієвої моделі:
Спробуйте замінити найближчий if (innerWidth < 768) на matchMedia("(min-width: 768px)"), і ви одразу відчуєте, наскільки чистішим стає код.



