Praca z RWD

Ostatnia aktualizacja: 08 lutego 2020

Przy pracy z różnymi urządzeniami bardzo często chcemy sprawdzać rozdzielczość urządzenia.

Jednym ze sposobów reakcji na zmianę rozmiaru ekranu przeglądarki, jest podpięcie się pod event resize obiektu window:


window.addEventListener("resize", e => {
    console.log(window);
});

Event ten najczęściej zastosujemy w sytuacjach, gdy chcemy wykonać jakiś skrypt reagując na zmianę rozmiarów okna (np. zmiana okna przeglądarki, lub obrócenie urządzenia), ale równocześnie reakcja taka powinna się odbywać w każdej rozdzielczości.


const banner = document.querySelector("#banner");

//po wejściu na stronę
banner.style.height = window.innerHeight + "px";

//i po zmianie rozmiarów okna
window.addEventListener("resize", e => {
    console.log(`Rozmiar okna: ${window.innerWidth} x ${window.innerHeight}`);
    banner.style.height = window.innerHeight + "px";
});

W naszym przypadku wykorzystywanymi właściwościami obiektu window są window.innerWidth i window.innerHeight. Ale to nie wszystkie możliwości. Jeżeli wypiszesz sobie w konsoli debugera obiekt window zobaczysz, że znajduje się tam jeszcze kilka przydatnych właściwości. Jedną z nich jest interfejs Screen, który dostępny jest pod właściwością window.screen:


console.log(window.screen);

//{
//    availWidth: 1680
//    availHeight: 1020
//    width: 1680
//    height: 1050
//    colorDepth: 24
//    pixelDepth: 24
//    availLeft: 0
//    availTop: 0
//    orientation: ScreenOrientation
//}

Gdy podepniesz się pod event resize, zauważysz w konsoli podczas zmiany rozmiarów okna, że jest odpalany bardzo, bardzo często. Przy wielu przypadkach nie powinno to być raczej problemem, ale przy bardziej skomplikowanych obliczeniach wewnątrz tego eventu trzeba uważać i w razie konieczności sięgnąć po inne techniki takie jak debounce, lub skorzystać z poniższego rozwiązania.

matchMedia

Kolejnym sposobem na reagowanie na zmianę mediów (w tym rozmiarów okna) jest skorzystanie ze specjalnie przeznaczonego do tego celu obiektu window.matchMedia(mediaQuery)


const media = window.matchMedia("(min-width: 768px)");

if (media.matches) {
    console.log("Wersja na desktopy");
} else {
    console.log("Wersja mobilna");
}

Zaletą tego rozwiązania jest to, że podane media mogą być tak samo precyzyjne jak te z CSS. Nie musimy się więc ograniczać do rozmiaru okna, ale też możemy sprawdzić inne media.

Dodatkowo w przeciwieństwie do eventu resize matchMedia nie jest odpalany wiele razy, a tylko w momencie gdy zachodzi test podany w nawiasach.

Powyższy kod zostanie odpalony jeden raz - tuż po wywołaniu (najczęściej przy wejściu na stronę).

Żeby sprawdzanie reagowało na zmianę mediów (np. rozmiaru okna), musimy podpiąć do niego nasłuchiwanie zmian:


const media = window.matchMedia("(min-width: 768px)");

//po wejściu na stronę
if (media.matches) {
    console.log("Wersja na desktopy");
} else {
    console.log("Wersja mobilna");
}

//nasłuchujemy zmian
media.addEventListener("change", e => {
    if (e.matches) {
        console.log("Wersja na desktopy");
    } else {
        console.log("Wersja mobilna");
    }
});

W przeciwieństwie do eventu resize który jest odpalany non stop przy zmianie rozmiaru okna, powyższy event będzie odpalany tylko w momencie danego warunku z media.


function setBg(e) {
    if (e.matches) {
        body.style.setProperty("background-color", "red");
    } else {
        body.style.setProperty("background-color", "blue");
    }
}

const media = window.matchMedia("(min-width: 768px)");
const body = document.querySelector("body");

setBg(media);

media.addEventListener("change", setBg);

Dla machMedia istnieją też dwie bardzo podobne funkcje, które służą do podpinania eventów. Mowa o addListener i removeListener.


        media.addListener(media => { ... });
        media.removeListener(media => { ... });
    

Obie funkcje nie są już zalecane na rzecz powyżej pokazanego klasycznego podpinania zdarzenia change.

Trening czyni mistrza

Jeżeli chcesz sobie potrenować zdobytą wiedzę z tego działu, to zadania znajdują się w repozytorium pod adresem: https://github.com/kartofelek007/zadania-rwd

W repozytorium jest branch "solutions". Tam znajdziesz przykładowe rozwiązania.

Wszelkie prawa zastrzeżone. Jeżeli chcesz używać jakiejś części tego kursu, skontaktuj się z autorem. Aha - i ta strona korzysta z ciasteczek.

Menu