Изучаем matchMedia API и object MediaQueryList
Продолжаем осваивать управление media queries при помощи javascript. На этот раз речь пойдёт о matchMedia API. Как результат работы - вы получите готовый шаблон, который можно смело внедрять в свои проекты.
В предыдущей статье, посвещенной enuire.js, мы говорили о том, как работать с media queries при помощи javascript. Enuire.js - замечательный инструмент для создания mobile-first сайтов и приложений, основанный на matchMedia API. Чтобы лучше понять тему, давайте с этим самым matchMedia и разберёмся.
Предпосылки и источники
Прежде всего, давайте разберёмся с совместимостью данной технологии с версиями браузеров. В этом нам поможет прекрасный сайт caniuse.com. Из таблицы видно, что все текущие версии браузеров, за исключением Opera Mini, поддерживают matchMedia. Что касается предыдущих версий - то тут, стоит обратить внимание главным образом на IE 9.0 и Opera 12.0, которые хотя и понимают CSS3 Media Queries, но не поддерживают matchMedia.
Проблемму совместимости помогают решить различные polyfill'ы, о которых мы уже говорили в предыдущей статье. Рекомендую обрать внимание на media-match.
Итак, приступим. Прежде всего, определимся с первоисточником. Для нас - это, конечно же, спецификация W3C. Если что-то из ниже описанного будет расходится со спецификацией или устареет - смело кидайте камнями (лучше, конечно, пишите в комментариях).
Рассмотрим простой пример
Допустим, нам необходимо добавлять к некоторому диву класс "some-class"
лишь в том случае, когда ширина экрана браузера больше или равна 768 пикс. Делается это очень просто:
[js]
if (window.matchMedia("screen and (min-width: 768px)").matches) {
div.addClass("some-class");
} else {
// ширина экрана меньше 768 пикселей
}
[/js]
Метод window.matchMedia()
принимает в качестве аргумента строку - media query (в нашем случае - это "screen and (min-width: 768px)"
) и возвращает объект MediaQueryList. В свою очередь, объект MediaQueryList имеет 2 атрибута и 2 метода.
Объект MediaQueryList
Media
- атрибут readonly (строка).Matches
- астрибут readonly (true/false). Определяет, совпал ли заданный media query с текущим размером экранаaddListener
- метод, "включающий" прослушку на изменение ширины экранаremoveListener
- метод, "выключающий" прослушку.
Вот вам скриншот из хрома, для пущей наглядности:
Начинаете понимать, как всё это работает? Window.matchMedia("screen and (min-width: 768px)")
возвращает нам объект MediaQueryList, в котором нас пока интересовал только атрибут matches
. Но данный пример сработает у нас только один раз, при инициализации. А что, если пользователь изменит размер экрана? Тут нам на помощь приходит метод addListener
.
Рассмотрим пример более жизненный
[js]
function setup_for_width(mql) {
if (mql.matches) {
div.addClass("some-class");
} else {
div.removeClass("some-class");
}
}
var mql = window.matchMedia("screen and (min-width: 768px)");
mql.addListener(setup_for_width); // Добавим прослушку на смену результата
setup_for_width(mql); // Вызовем нашу функцию
[/js]
Прежде всего мы объявляем функцию setup_for_width()
, в которую будем передавать объект MediaQueryList (mql). Функция очень проста. Если mql.matches
= true
, то добавляем класс "some-class"
к диву. В противном случае, удаляем этот класс.
Далее, объявляем переменную mql, в которую записываем созданный объект MediaQueryList.
После чего "включаем" прослушку addListener на изменение объекта mql. При каждом его изменении будет вызываться функция setup_for_width()
, а значит удаляться/добавляться класс "some-class"
, чего мы, в конечном итоге, и добивались.
В заключение, вызовем нашу функцию setup_for_width(mql), чтобы она сработала в момент первой загрузки страницы (до первого изменения media query).
Задача выполнена! Вы можете смело использовать данный шаблон на своих проектах, главное не забудьте о поддержке более ранних версий браузеров. Кстати, о том, как правильно подключать polyfill (для тех, кто ещё не умеет пользоваться modernizr), я говорил в предыдущем уроке :) Возникнут вопросы - пишите!