Перейти к содержанию

window.matchMedia()

Определение

window.matchMedia() – метод JavaScript, который проверяет, соответствует ли документ CSS-медиазапросу. Возвращает MediaQueryList со свойством matches и событием change для слежения за брейкпоинтами и темой ОС.

3 мин 33 Обновлено 12 августа

Метод window.matchMedia() – мост между CSS-медиазапросами и JavaScript: те же условия, что в правиле @media – «(max-width: 600px)» или «(prefers-color-scheme: dark)», – можно разово проверить и отслеживать из скрипта. Метод описан в спецификации CSSOM View и работает во всех браузерах с июля 2015 года (в Internet Explorer – с версии 10), так что полифилы не нужны. На практике matchMedia() закрывает три типовые задачи: переключение JS-логики на брейкпоинтах, определение тёмной темы пользователя и уважение к настройке уменьшенного движения – последнее уже вопрос доступности.

Как это работает

Вызов window.matchMedia("(max-width: 600px)") возвращает объект MediaQueryList с двумя свойствами: matches – булево значение, соответствует ли документ запросу в момент чтения, и media – сериализованная строка самого запроса. Синтаксис строки – ровно как в CSS: media-функции обязаны стоять в скобках ("(max-width: 600px)" – верно, "max-width: 600px" – ошибка), а типы (screen, print, all) и операторы and, or, not, only пишутся без скобок.

Для слежения за изменениями MediaQueryList генерирует событие change. Оно срабатывает при пересечении границы условия в любую сторону: окно сузилось ниже брейкпоинта – событие, расширилось обратно – снова событие. Обработчик получает объект MediaQueryListEvent с теми же свойствами matches и media. Важный нюанс: при загрузке страницы change не срабатывает – начальное состояние проверяют через свойство matches и при необходимости вызывают обработчик один раз вручную.

  • addEventListener("change", handler) – современный способ подписки: MediaQueryList наследует EventTarget, событие доступно во всех браузерах (Baseline) с сентября 2020 года.
  • addListener() / removeListener() – устаревшие (deprecated) методы. Единственная причина, по которой они задерживались в коде – Safari до версии 14, где MediaQueryList ещё не наследовал EventTarget. В новом коде им делать нечего.

matchMedia и событие resize – в чём разница

До matchMedia адаптивную JS-логику строили на слушателе resize: на каждое изменение размера окна скрипт читал innerWidth и сравнивал с числом. Разница принципиальная:

Сравнение matchMedia и слушателя resize
КритерийmatchMedia + changeresize + innerWidth
Частота вызововТолько при пересечении брейкпоинтаНа каждый пиксель изменения окна
УсловияТе же строки, что в CSS @mediaЧисла, продублированные в JS
Синхронность с вёрсткойБрейкпоинты гарантированно совпадают с CSSЛегко разъезжаются при правке стилей
ВозможностиЛюбые media-функции: тема, ориентация, движениеТолько размеры окна

Зачем это нужно

JS-брейкпоинты. Тяжёлую функциональность включают только там, где она нужна: слайдер или карта инициализируются на десктопе, мобильное меню – на узких экранах. Обработчики вешаются и снимаются в момент пересечения брейкпоинта, а не проверяются на каждое движение окна – это экономит ресурсы, что особенно заметно на мобильных устройствах. Если интерактивных элементов много, обработчики удобно вешать через делегирование событий – тогда при смене режима достаточно заменить один слушатель на контейнере.

Тёмная тема. Запрос window.matchMedia("(prefers-color-scheme: dark)") сообщает, что пользователь выбрал тёмную тему в настройках операционной системы, а подписка на change ловит переключение на лету – например, при автоматической смене темы вечером. Результат обычно записывают в класс или data-атрибут на корневом элементе, и дальше работает CSS.

Уменьшенное движение. Запрос window.matchMedia("(prefers-reduced-motion: reduce)") – тот же паттерн для пользователей, которым анимации мешают или физически вредят. CSS-анимации отключает медиазапрос в стилях, а matchMedia закрывает JS-часть: автопрокрутку, параллакс, декоративные эффекты, запущенные скриптами.

Правило выбора простое: если задача решается чистым CSS-медиазапросом, JavaScript не нужен вообще. matchMedia берут тогда, когда на брейкпоинте меняется поведение, а не только внешний вид: другая логика событий, другие обработчики, другие данные.

Пример

Слежение за мобильным брейкпоинтом с корректной обработкой начального состояния:

const mql = window.matchMedia("(max-width: 600px)");

function onBreakpoint(e) {
  if (e.matches) {
    initMobileMenu();
  } else {
    destroyMobileMenu();
  }
}

mql.addEventListener("change", onBreakpoint);
onBreakpoint(mql); // вызвать вручную: change при загрузке не сработает

Обработчик принимает и MediaQueryListEvent, и сам MediaQueryList – у обоих есть свойство matches, поэтому одна функция обслуживает и загрузку страницы, и все последующие изменения.

Определение тёмной темы с реакцией на смену настроек ОС:

const darkMode = window.matchMedia("(prefers-color-scheme: dark)");

document.documentElement.classList.toggle("dark", darkMode.matches);

darkMode.addEventListener("change", (e) => {
  document.documentElement.classList.toggle("dark", e.matches);
});

На Битрикс-проектах я использую этот паттерн, когда мобильная и десктопная версии различаются поведением: например, галерея, которая на широком экране работает как сетка, а на мобильном превращается в слайдер. Инициализация и уничтожение слайдера привязаны к событию change – скрипт не дёргается впустую на каждом resize, а условия брейкпоинтов совпадают с CSS-файлом один в один. Отдельный плюс для аудита: единые условия в CSS и JS проще проверять – расхождение мобильной вёрстки и мобильной логики находится за минуты, а не всплывает жалобами пользователей.

Частые вопросы

Что возвращает window.matchMedia()?

Объект MediaQueryList. У него два свойства: matches – булево значение, соответствует ли документ медиазапросу прямо сейчас, и media – сериализованная строка самого запроса. Этот же объект генерирует событие change при изменении результата запроса.

Как следить за изменением медиазапроса в JavaScript?

Подписаться на событие change: mql.addEventListener('change', handler). Обработчик получает объект MediaQueryListEvent со свойством matches. При загрузке страницы change не срабатывает, поэтому для начального состояния обработчик вызывают один раз вручную сразу после подписки.

Чем matchMedia лучше слушателя resize?

Событие change срабатывает только при пересечении границы условия, а resize – на каждый пиксель изменения окна, то есть сотни раз за одно перетаскивание. Условия matchMedia совпадают с CSS-брейкпоинтами буквально, а не продублированы числами в JS, и покрывают любые media-функции: тему, ориентацию, уменьшенное движение.

Можно ли ещё использовать addListener() и removeListener()?

Они официально устарели (deprecated). Единственная причина, по которой они задерживались в коде – Safari до версии 14, где MediaQueryList не наследовал EventTarget. В новом коде используют addEventListener('change') и removeEventListener – событие доступно во всех браузерах (Baseline) с сентября 2020 года.

Как определить тёмную тему пользователя из JavaScript?

Разовая проверка: window.matchMedia('(prefers-color-scheme: dark)').matches вернёт true, если в операционной системе выбрана тёмная тема. Чтобы реагировать на переключение темы на лету, подписываются на событие change этого же объекта MediaQueryList.

Почему matchMedia('max-width: 600px') не работает?

Синтаксис строки запроса – как в CSS: media-функции обязаны стоять в скобках. Правильно: matchMedia('(max-width: 600px)'). Без скобок строка не является корректным медиазапросом. Типы (screen, print, all) и операторы and, or, not, only при этом пишутся без скобок.

Срабатывает ли событие change при загрузке страницы?

Нет. Событие генерируется только при изменении результата запроса – например, когда окно пересекло брейкпоинт или пользователь сменил тему ОС. Начальное состояние проверяют через свойство matches и при необходимости вызывают обработчик вручную один раз.

Связанные термины

Материалы по теме

Что почитать дальше по этой теме

Статья Что боты находят на сайте, а вы – нет Боты ходят по изнанке сайта, куда живой человек не забредёт, и фиксируют в логах то, чего не видно ни в Метрике, ни на витрине: падающие с ошибкой 500 страницы каталога, битый файл с 747 обращениями, поток сканеров секретов. Разбираю на реальных логах, что искать и как чинить. 7 мин 216 22 июля 2026 Инструкция Как выгрузить и читать access-логи, если хостинг хранит их три дня Access-лог – единственное место, где виден весь трафик сайта, включая ИИ-ботов, которых не замечают счётчики. Разбираю на практике: где взять логи, как не потерять их из-за ротации, какие команды показывают ботов, ошибки и подозрительную активность. 7 мин 170 21 июля 2026 Флагманский гайд AI-анализ email-обращений: методика на стыке Яндекс.Метрики и Claude Code Классический email-трекинг отвечает на вопрос «откуда пришло обращение». AI-слой отвечает на вопросы, которые раньше требовали ручного аналитика: значим ли email на фоне звонков, форм и мессенджеров, почему один источник даёт качественные обращения, а другой – пустые, какие сегменты визитов предшествуют письму, что написать в ответ с учётом пути пользователя. Здесь – как я собираю это на уже имеющемся стеке: Logs API Метрики, PostgreSQL и Claude Code, без новых платных сервисов. 11 мин 297 26 мая 2026 Флагманский гайд Майкор: ИИ-аудит проекта по 4 точкам контакта Майкор – это перекрёстный ИИ-аудит проекта в 4 точках контакта: сайт, контекстная реклама, AI-поиск и Яндекс.Карты. Я анализирую каждую систему и смотрю связки между ними – где маркетинг рассказывает одно, реклама ведёт на другое, а AI-системы цитируют третий номер телефона. В одном из моих аудитов медицинской клиники в Москве у организации в индексе AI-сервисов оказалось 6 разных номеров и всего 7 упоминаний на 64 проверочных запроса – при том, что в обычной выдаче Яндекса клиника была в топ-1. Майкор закрывает такие разрывы за один аудит вместо четырёх раздельных. 16 мин 501 13 мая 2026 Гайд FAQPage Schema: как разметить блок частых вопросов и попасть в AI-ответы FAQPage schema – один из самых эффективных типов разметки для попадания в AI-ответы. Страницы с FAQPage schema цитируются AI-поисковиками в 2,7 раза чаще. В этом гайде – формат разметки, правила написания ответов для AI, реализация на 1С-Битрикс и типичные ошибки, которые обнуляют эффект. 8 мин 331 25 апреля 2026