Javascript and windows media

Как и зачем использовать медиа-запросы в JavaScript

Медиа-запросы, впервые представленные в CSS3, составляют основной компонент адаптивного веб-дизайна. Приложения должны быть адаптированы к ограничениям каждого типа устройства (например, мобильных телефонов, планшетов, ноутбуков, настольных компьютеров), и медиа-запросы обеспечивают простой способ установки размеров области просмотра в зависимости от размера устройства, на котором работает приложение.

Медиа-запросы позволяют не только изменять размеры области просмотра в зависимости от размера экрана, но также могут помочь вам установить различные свойства стиля для разных устройств, включая цветовые схемы, стили шрифтов, настройки движения и анимацию, границы и интервалы, и почти любой другой CSS.

На первый взгляд некоторые фронтенд-разработчики упускают из виду тот факт, что медиа-запросы также поддерживаются в JavaScript. Хотя они в JavaScript не так популярны, как в CSS, они обеспечивают гибкость и ряд преимуществ, которые могут сделать их лучшим выбором для определенных случаев использования.

Преимущества медиа-запросов в JavaScript

В этот момент вы можете подумать: с какой стати разработчику использовать JS медиа-запросы, когда он может использовать CSS3?

Медиа-запросы JavaScript обладают двумя основными преимуществами.

  1. Гибкость: вы можете программно включать медиа-запросы в свой код JavaScript, чтобы они запускались только при наступлении определенного события или при выполнении определенных условий. При подходе, основанном только на CSS3, изменения, описанные медиа-запросом, вступают в силу для каждого события изменения размера экрана.
  2. Удобство: медиа-запросы JavaScript используют тот же синтаксис, к которому вы привыкли при работе с CSS.

Подумайте над этим: что, если вы хотите динамически изменять свойства для разных размеров экрана? Вы все еще можете чесать голову, настаивая на том, что что-то вроде этого будет работать нормально:

В блоке кода выше у нас есть оператор «if», основанный на том, что он меньше 1024 (т.е. стандартный размер экрана для дисплеев рабочего стола). Предположительно, этот метод должен запускаться каждый раз, когда приложение работает на устройстве, меньшем, чем настольный компьютер.

К сожалению, этот метод дорогостоящий, потому что он будет срабатывать при каждом изменении размера, а не только тогда, когда пользователь открывает приложение на своем мобильном телефоне или планшете. Правильно — этот метод будет запускаться каждый раз, когда пользователь вручную изменяет размер экрана на настольном компьютере. Чрезмерное количество таких операций в конечном итоге может привести к зависанию приложения.

К счастью, у нас есть идеальный API для обработки динамических ситуаций и дизайна ответов: поприветствуйте matchMedia API.

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

Вместо того, чтобы прикреплять слушателей к событию изменения размера, как мы это делали в приведенном выше примере, мы можем использовать API matchMedia.

Метод matchMedia() интерфейса Window по существу присоединяет слушателей к медиа-запросам, но не реагирует на каждое изменение размера окна или экрана, что приводит к значительному повышению производительности. Если мы воспользуемся преимуществом этого метода, мы несем ответственность только за разработку логики, которую мы хотим выполнить для изменения размера экрана, не беспокоясь о других условиях, проверках и оптимизации кода.

Чтобы использовать этот API, мы вызываем и передаем строку медиа-запроса window.matchMedia() , определяющую размер экрана, на который мы хотим ответить.

Метод matchMedia () возвращает новый объект MediaQueryList, который мы назвали mQuery в приведенном выше примере. Этот объект хранит информацию о медиа-запросе, примененном к конкретному документу, а также вспомогательные методы для управляемого событиями и немедленного сопоставления. Это позволяет нам запускать настраиваемую логику в начале события изменения размера.

Чтобы выполнить необходимую логику изменения размера, нам нужно проверить window.matches, логическое свойство, которое возвращает «истину», если медиа-запрос совпал, и «ложь», если нет. В нашем примере это свойство сообщает нам, было ли фактическое соответствие указанному условию (т.е. минимальная ширина экрана составляет 320 пикселей).

Легко, правда? Есть только одна загвоздка: window.matches может выполнить эту проверку только один раз. Чтобы облегчить адаптивный веб-дизайн, мы хотим постоянно проверять любые происходящие изменения. К счастью, есть еще один инструмент, который мы можем объединить с windows.matches, чтобы помочь нам в этом: метод addListener().

Читайте также:  Access для windows mobile

Метод addListener()

API matchMedia предоставляет метод addListener() , а также соответствующий метод removeListener(). Когда мы вызываем addListener() , мы передаем функцию обратного вызова, которая запускается всякий раз, когда обнаруживает изменение статуса соответствия медиа-запроса. Эта функция обратного вызова — функция, которая должна запускаться при изменении размера:

Этот метод позволяет нам реагировать на изменения медиа-запросов и динамически вызывать дополнительные методы по мере необходимости. Эти динамически вызываемые методы могут затем изменять различные свойства документа, такие как стили шрифтов, границы и интервалы, анимацию и многое другое.

Например, если вы хотите добавить динамический стиль шрифта, вы можете добиться этого примерно так:

Вывод

Теперь вы должны иметь общее представление о медиа-запросах в JavaScript и о том, как они обеспечивают эффективный адаптивный дизайн. MatchMedia API может помочь вам создать медиа-запрос на JavaScript, а addListener() может позволить вам создать адаптивный кроссплатформенный интерфейс, вызывая функции обратного вызова.

Периодический опрос на предмет изменений состояния документа — это неэффективный и ресурсоемкий подход, который в конечном итоге приведет к задержке приложения. Использование matchMedia() позволяет нам наблюдать за конкретным документом, обнаруживать изменения в условиях медиа-запроса и программно изменять свойства документа в зависимости от статуса медиа-запроса.

Работаем с медиа-запросами через JavaScript

Что в первую очередь приходит на ум, когда вы думаете о медиа-запросах? Может быть, что-то типа такого в файле CSS:

Медиа-запросы CSS — ключевой компонент любого адаптивного дизайна. Это отличный способ применить разные стили к разным контекстам, будь то на основе размера области просмотра, предпочтительной цветовой схемы, определенных взаимодействий и, черт возьми, даже определенных устройств, таких как принтеры, телевизоры и проекторы, и многих других.

Но знаете ли вы, что у нас есть медиа-запросы и для JavaScript? Это так! Возможно, мы не так часто видим их в JavaScript, но определенно есть варианты их использования, которые я на протяжении многих лет считаю полезными для создания адаптивных плагинов, таких как слайдеры. Например, при определенном разрешении вам может потребоваться перерисовать и пересчитать элементы слайдера.

Работа с медиа-запросами в JavaScript сильно отличается от работы с ними в CSS, хотя концепции схожи: сопоставьте некоторые условия и примените некоторые вещи.

Использование matchMedia()

Чтобы определить, соответствует ли документ строке медиа-запроса в JavaScript, мы используем метод matchMedia() . Несмотря на то, что он официально является частью спецификации модуля представления объектной модели CSS, находящейся в статусе рабочего проекта, его поддержка браузером великолепна начиная с Internet Explorer 10 с глобальным охватом 98,6%.

Эти данные о поддержке браузера взяты из Caniuse, в котором есть более подробная информация. Число означает, что браузер поддерживает эту функцию в этой версии и выше.

Desktop

Chrome Firefox IE Edge Safari
9 6 10 12 5.1

Mobile / Tablet

Android Chrome Android Firefox Android iOS Safari
85 79 3 5.0-5.1

Использование почти идентично медиа-запросам в CSS. Мы передаем строку медиа-запроса в matchMedia(), а затем проверяем свойство .matches .

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

Это базовое использование для сопоставления условий медиа запросов в JavaScript. Мы создаем условие соответствия (matchMedia()), которое возвращает объект (MediaQueryList), проверяем его (.matches), а затем делаем что-то, если условие оценивается как true.

Но это еще не все. Например, если бы мы изменим размер окна, ничто само по себе не обновиться в отличии от CSS. Это потому, что .matches идеально подходит для одноразовых мгновенных проверок, но оно не может постоянно проверять наличие изменений. Значит, нам нужно что то еще…

Отслеживание изменений

MediaQueryList имеет метод addListener() (и последующий removeListener()), который принимает функцию обратного вызова (представленную событием .onchange), которая вызывается при изменении статуса медиа-запроса. Другими словами, мы можем запускать дополнительные функции при изменении условий, что позволяет нам «реагировать» на обновленные условия. Пример использования:

Один-два шага matchMedia() и MediaQueryList дают нам такую же возможность не только соответствовать условиям медиа-запроса, которые предоставляет CSS, но и активно реагировать на обновленные условия.

Когда вы регистрируете слушатель событий с помощью addListener(), он изначально не запускается. Нам нужно вызвать функцию обработчика событий вручную и передать медиа-запрос в качестве аргумента.

Старый способ

Ради справки — и немного ностальгии — я хотел бы осветить старый (хотя все еще популярный) способ выполнения «медиа-запросов» в JavaScript. Наиболее распространенный подход — привязка слушателя событий изменения размера, который проверяет window.innerWidth или window.innerHeight.

Вы все еще можете столкнуться с таким кодом:

Поскольку событие изменения размера вызывается при каждом изменении размера браузера, это дорогостоящая операция! Глядя на влияние пустой страницы на производительность, мы можем увидеть разницу.

Это на 157% больше Scripting

Еще более простой способ увидеть разницу — с помощью журнала консоли.

Это 208 событий изменения размера по сравнению с шестью совпадающими медиа-событиями.

Даже если не обращать внимания на проблемы с производительностью, изменение размера является ограничительным в том смысле, что не позволяет нам писать расширенные медиа-запросы для таких вещей, как печать и ориентация. Таким образом, хотя он и имитирует поведение «медиа-запроса», позволяя нам согласовывать ширину области просмотра, он не способен сопоставить большую часть чего-либо еще — и мы знаем, что настоящие медиа-запросы способны на гораздо большее.

Заключение

В этой статье мы рассмотрели медиа-запросы в JavaScript! Мы узнали о matchMedia(), которое позволяет нам определять условия медиа запросов, и рассмотрели объект MediaQueryList, который позволяет нам выполнять одноразовые (.matches) и постоянные (addListener()) проверки условий, чтобы мы могли реагировать на изменения (.onchange) вызывая соотвествующие функции.

Мы также рассмотрели «старый» способ, отслеживая события изменения размера в окне. Хотя он по-прежнему широко используется и является вполне обычным способом реагировать на изменения размера window.innerWidth, он не может выполнять проверки расширенных условий медиа запросов.

В завершение статьи приведем полезный пример, который невозможно реализовать по-старому. С помощью медиа-запроса проверю, находится ли пользователь в ландшафтном режиме. Этот подход распространен при разработке игр HTML5, и его лучше всего просматривать на мобильном устройстве.

Javascript and windows media

There may be times when, in addition to CSS, you also need to do something in JavaScript when a CSS media query is matched. While CSS purists may cower at the idea of mixing the two when it comes to handling media queries, at the end of the day, having JavaScript on board just means an additional tool in our «responsive» arsenal, and a very robust tool at that.

In JavaScript, you can detect for the same CSS media query string defined in CSS with the method window.matchMedia() . For example, in CSS, if you have the following CSS media query:

/* #### CSS that’s applied when the viewing area’s width is 765px or less #### */
@media screen and (max-width: 765px) <
/* CSS definitions here */
>

To detect the same media query in JavaScript, you’d do the following:

var mql = window.matchMedia(«screen and (max-width: 765px)»)

Notice the query string entered in both cases is identical with the exception of » @media » in the former case. That’s the beauty of the JavaScript set up- it pretty much mirrors the construct of its CSS counterpart. window.matchMedia() returns a MediaQueryList object containing a couple of methods and properties, the most frequently used being the » matches » property. It’s a Boolean property that returns true if the media query matches the state of the current window, and false if not. More on this later.

Browser compatibility wise, window.matchMedia() is supported in FF6+, IE10+, Chrome/ Safari, and Opera 12+. To test for browser support, you can simply test for support for the property window.matchMedia .

window.matchMedia() in detail

When you call window.matchMedia() , it returns a MediaQueryList object, which really is just an ordinary JavaScript object containing some useful methods and properties for us to examine the outcome of the match. Lets look at the returned properties first.

window.matchMedia() returned properties

Property Description
matches Boolean that returns true if the current state of the window matches the conditions defined in the CSS query string, or false if not.
media Returns the serialized media query list. In the case of the operation:

var mql = window.matchMedia(«screen and (max-width: 765px)»)

mql.media would return in NON IE browsers:

«screen and (max-width: 765px)»

and in IE (as of IE11) browsers, the same value, but with no space between a property and its value:

«screen and (max-width:765px)»

Furthermore, in IE, if a media is not specified (ie: » screen «) inside the media query list, it returns » all » instead. So for the following operation:

var mql = window.matchMedia(«(max-width: 765px)»)

The property mql.media returns » (max-width: 765px) » in non IE browsers, but » all and (max-width:765px) » in IE instead.

Due to these differences, when probing the media property to determine the type of incoming media query, you should use regular expressions to equalize the slight differences in the return value between browsers.

The property you’ll most frequently be referring to is » matches «, which returns true when our constructed media query matches the current state of the window. The following easily checks at run time if the user’s browser width is 800px or more:

var mql = window.matchMedia(«screen and (min-width: 800px)»)
if (mql.matches) < // if media query matches
alert(«Window is 800px or wider»)
>
else <
// do something else
>

Now, the above code only runs the desired CSS media query and compares it to the current window state once at run time, and doesn’t react to any changes to the later thereafter. At this point the code is hardly responsive. In order to utilize window.matchMedia() in a responsive manner, we need to also make use of its methods/ event handlers:

window.matchMedia() returned methods/ event handlers

method Description
addListener( functionref) Adds a new listener function, which is executed whenever the state of the window changes and triggers a re-evaluation of the defined CSS media query.
removeListener(functionref) Removes a previously added listener function from listening in on changes between the current state and the defined CSS media query.

The key method to befriend is addListener() . By a function to wrap the code we want to run and enter it into addListener() , our function will now fire whenever any changes to the current window state leads to a match against the defined CSS media query. In other words, our code can now react to not just a CSS media query match at run time, but whenever the window state changes..

The following code uses addListener() to react to a CSS media query not just on run time, but also when any changes to the window state occur:

function mediaqueryresponse(mql) <
if (mql.matches) < // if media query matches
console.log(«The condition » + mql.media + » has been met»)
>
else <
console.log(«Condition not met yet»)
>
>

var mql = window.matchMedia(«screen and (max-device-width: 480px) and (orientation: portrait)»)
mediaqueryresponse(mql) // call listener function explicitly at run time
mql.addListener(mediaqueryresponse) // attach listener function to listen in on state changes

Here we’ve defined a listener function mediaqueryresponse() . Notice how such a function is inexplicitly passed the MediaQueryList object from the call to window.matchMedia() , allowing our function to process the result. One curious line in the above code is the call to our mediaqueryresponse() function, in addition to passing it into addListener() . This may seem redundant, but it’s important to note that addListener() only fires when the state of the window changes, which doesn’t occur when the page first loads. The explicit call to mediaqueryresponse() ensures that this function is also executed when the page loads.

Now we have all the pieces in JavaScript to respond to a CSS media query. One caveat of bringing JavaScript into the equation is often the need to duplicate the media query twice in your page- once in your CSS @media rule, and again in JavaScript, depending on what you’re trying to do. This could lead to maintenance issues, as it’s easy to change one query but forget to update the same for the other. But that’s really a small price to pay for the added robustness the language brings to sculpting responsive pages.

Читайте также:  Virtual folder in windows
Оцените статью