Přejít k navigační liště

Zdroják » Webdesign » Media queries v JavaScriptu

Media queries v JavaScriptu

Ukážeme vám, jak v JavaScriptu používat @media pravidla podobně jako v CSS.

Nálepky:

Text vyšel původně na autorově webu.

Pokud se zobrazení stránky liší dle rozměrů viewportu díky použití @media pravidla, je občas nutné tomu přizpůsobit i JavaScript.

Třeba nevolat zbytečné JS akce typu fixování elementů a podobně.

Detekce podle šířky

První možnost je zkrátka jednoduše měřit šířku viewportu:

var sirka = document.documentElement.clientWidth;
if (sirka > 1024) {
  // nějaký kód
}

Asi největší problém je v tom, že je šířka stránky v pixelech. Pokud se v CSS @mediapravidlech používají nějaké rozumnější jednotky (např. em), nejde to rozumně skloubit dohromady.

Druhý problém je v tom, že se breakpointy nastavují zvlášť v JS i CSS.

Metoda matchMedia

Přímo v JS existuje metoda fungující obdobně jako media queries v CSS:

if (window.matchMedia("(max-width: 40em)").matches) {
  // kód pro viewport do 40 em
}

Podmínku je nutné uvést včetně závorek okolo.

Podpora v prohlížečích

Dobře podporovaná vlastnost (funguje i v IE 10 a novějších). Pro starší prohlížeče jde navíc použít polyfill, který podporu doplní – matchMedia.js (pro reakci na změnu velikosti okna je potřeba i matchMedia.addListener.js).

Změna velikosti okna

Hodně užitečná je i schopnost sledovat změnu šířky okna/viewportu pomocí přidání posluchače přes addListener pro podmínku.

Není tak nutné využívat událost onresize. Navíc se detekuje pouze změna (jindy se funkce nezavolá), takže se nemusí stav šířky ukládat do nějaké proměnné, aby se daný kód nevolal zbytečně opakovaně.

var mql = window.matchMedia("(max-width: 40em)");

// funkce, která se zavolá při změně
mql.addListener(zmenaMedia);

// může se zavolat i po načtení stránky
zmenaMedia(mql);

// samotná funkce
function zmenaMedia(mql) {
  if (mql.matches) {
    // kód pro viewport do 40 em
  }
}

Kód uvnitř podmínky se spustí po načtení stránky v okně do 40em. Případně se spustí právě jednou pokaždé, když se viewport zmenší pod stanovenou hranici. Při dalším zmenšování už se znovu neprovádí, protože nedošlo ke změně.

Sdílení @media pravidel

K úvaze je, kterak sdílet hodnoty break-pointů mezi JS a CSS.

První možnost je mít nějaký konfigurační soubor se všemi break-pointy a ten v build procesu propsat do CSS i JS.

Jiná možnost je…

Předávání aktivního pravidla v content

Asi jediná možnost, jak si z CSS předat něco čitelného JavaScriptem bez úprav HTML, je použít vlastnost content.

Jde například elementu nastavit různé hodnoty do vlastnosti content podle aktivního @media pravidla:

html:before {
  display: none;
  content: "desktop";
}

@media (max-width: 40em) {
  html:before {
    content: "mobile";
  }
}

Nyní stačí při změně šířky okna zjišťovat výsledný styl pomocí getComputedStyle. Ve vlastnosti content u html:before bude desktop nebo mobile (v závislosti na šířce viewportu).

Trochu paradoxní je, že tento postup nepotřebuje (při načtení stránky) JS metodu matchMediaMatchování totiž proběhne už v CSS. Pro ošetření stavu při změně šířky by se ale už musel aktuální stav skriptem zjišťovat.

Detekční element

Jiná možnost je pomocí media queries nastavit nějakému elementu určité styly a ty potom v JS kontrolovat.

Třeba zapínat/vypínat viditelnost a tu potom skriptem detekovat.

Hotové řešení předání @media pravidel

Pro elegantnější práci s více @media podmínkami se nabízí do contentu předat jednotlivá pravidla a podle toho si sestavit „spouštěče“ s využitím matchMedia.

Třeba jako JSON:

html:before {
    display: none;
    content: '{"tablet" : {"min-width" : "40em", "max-width" : "60em"}}';
}

Použití je následovné:

MediaQueries.init({
    'tablet': function (matched) {
        if (matched) {
            // Jsem tablet
        }
        else {
            // Nejsem tablet
        }
    }
});

Výkon

Je možné, že detekce přes matchMedia a spouštění nějaké akce jen při změně bude efektivnější s ohledem na výkon, než neustálé zjišťování aktuálního breakpointu ve window.onresize.

Stejně tak je možný opak. Změřené to nemám. Pokud máte nějaké zkušenosti s výkonem matchMedia, dejte mi prosím vědět do komentářů.

Komentáře

Odebírat
Upozornit na
guest
0 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.