Media Queries w JavaScript
W tym wpisie poruszymy prostą, acz bardzo przydatną metodę dostępną od jakiegoś czasu w Obiektowym Modelu Dokumentu, która pozwoli nam lepiej kontrolować wygląd i…
W tym wpisie poruszymy prostą, acz bardzo przydatną metodę dostępną od jakiegoś czasu w Obiektowym Modelu Dokumentu, która pozwoli nam lepiej kontrolować wygląd i zachowanie naszych stron i aplikacji internetowych, które dostosowujemy do urządzeń mobilnych.
Mowa o metodzie matchMedia obiektu window
.
Jak działa matchMedia?
Jeśli wiesz czym są CSS Media Queries, to szybko zrozumiesz, z czym mamy teraz do czynienia. Otóż wyobraź sobie, że możemy z poziomu kodu JavaScript przekazać przeglądarce dowolne media query i zapytać czy w danym momencie spełnia ono warunek. Media query może wyglądać następująco:
screen and (max-width: 480px)
Wiemy, że przy takim zapisie w CSS, style zostaną zaaplikowane jedynie wówczas, gdy mamy do czynienia z urządzeniem posiadającym ekran i aktualną szerokością okna nie większą niż 480px.
Przekażmy zatem powyższy zapis do metody matchMedia
. Metodę tę wywołujemy z poziomu obiektu window
w ten sposób:
var mobileViewport = window.matchMedia("screen and (max-width: 480px)");
Do zmiennej mobileViewport
zwrócona zostanie referencja do obiektu MediaQueryList
(polecam podejrzeć w konsoli przeglądarki).
Teraz możemy zapytać, czy aktualna szerokość okna spełnia nasze warunki w ten sposób:
if(mobileViewport.matches) { // viewport <= 480px } else { // viewport > 480px }
Ok, ale gdzie tu dynamika?
No właśnie. W powyższym przykładzie sprawdzamy, czy okno przeglądarki ma odpowiednią szerokość. Oczywiście do media query możemy dodać inne warunki znane z CSS, np. orientację ekranu itd. Problem jest jednak taki, że powyższe sprawdzenie wykonywane jest jednorazowo, a my otrzymujemy z .matches
true
lub false
. Naszym celem będzie jednak wykonanie określonej funkcji na przykład wówczas, gdy zmieni się szerokość okna przeglądarki.
.addListener na ratunek
Dobra wiadomość jest taka, że do MediaQueryList
możemy przypisać event listener w taki sposób
mobileViewport.addListener(function(mq) { if(mq.matches) { // viewport <= 480px } else { // viewport > 480px } });
Funkcja zwrotna będzie wywoływana za każdym razem, gdy zmieni się warunek. W naszym przypadku, kiedy będziemy skalowali okno przeglądarki i zmniejszymy jego szerokość do 480px lub mniej, to jednokrotnie zostanie wywołana powyższa funkcja zwrotna. Gdy ponownie “wyskoczymy” powyżej wartości 480px, funkcja znów zostanie odpalona.
Z tego powodu w powyższej funkcji sprawdzamy za każdym razem, czy warunek media query jest spełniony. Jak wcześniej, odwołujemy się do mq.matches
i dzięki temu możemy odpowiednio zmienić coś na stronie, np. opcje slidera, które będą inne dla wersji desktopowej itd.
Ważna uwaga jest jednak taka, że jeśli chcemy zaraz po wczytaniu się strony wywołać wspomnianą funkcję sprawdzającą, to musimy ją zapisać w zmiennej i wywołać “ręcznie”, a następnie jak wyżej przypisać do .addListener
, gdyż event ten wywoływany będzie dopiero później (w naszym przypadku przy skalowaniu okna).
Oprócz .addListener
, mamy również metodę .removeListener
, która usunie funkcję zwrotną.
Dlaczego korzystać z .matchMedia?
Być może niejednokrotnie napisałeś kod jQuery tego typu:
window.on("resize", function() { if($(this).width() <= 480) { // viewport <= 480px } });
Powyższe rozwiązanie nie jest dobrą praktyką, gdyż podczas skalowania okna przeglądarki bardzo wiele razy odpalimy funkcję zwrotną, która następnie zamknie obiekt window
w obiekcie jQuery, a dopiero później sprawdzi szerokość skalowanego właśnie okna przeglądarki.
Dużo prościej wykonać tą samą czynność z .matchMedia
, gdyż funkcja zwrotna zostanie wywołana jedynie raz, gdy warunek zostanie spełniony i drugi raz, gdy “wyskoczymy” poza 480px.
Dodatkowo oczywiście sprawdzić możemy orientację urządzenia np. poprzez orientation: landscape
itd. Wówczas, gdy użytkownik przekręci telefon, media query spełni warunek, a nasza funkcja również zostanie wywołana.
Osobiście korzystam z takiego rozwiązania np. wtedy, gdy na stronie desktopowej umieszczam slider lub karuzelę. Podczas skalowania okna przeglądarki pojawia się potrzeba zmiany pewnych ustawień wspomnianych pluginów i to jest dobra metoda, by tego dokonać.
Wsparcie
Dobre wiadomości! Metoda .matchMedia
jest dobrze wspierana zarówno w przeglądarkach desktopowych jak i mobilnych. Wsparcie możesz zobaczyć tutaj.