@media pravidla v CSS

CSS umožňuje, aby se některá pravidla použila jenom za určitých podmínek. Tyto podmínky se dají popsat pomocí pravidel @media a chlupatých závorek. Využívá se toho hlavně pro dobrou čitelnost stránek na mobilech.

Příklady CSS zápisů s @media

Příklady podle šířky prohlížeče

@media (min-width: 600px) {
    body {background-color: yellow;}
}

Pokud je šířka okna 600px nebo širší (tedy je minimálně 600px), stránka (tag body) bude mít žluté pozadí.

Příklad zápisu kombinace podmínek pomocí spojky and:

@media (min-width: 414px) and (max-width: 556px){
    ... styl jen pro určitou šířku mobilů
}

Jak je zvykem u and, obě závorky musí platit zároveň. Výklad níže.

Další příklad s ukázkou, k čemu se to dá třeba použít:

div.boxik {float: right; width: 300px;}

@media (max-width: 414px) {
    div.boxik {float: none; width: 100%;}
    /* další styly pro mobilní telefon */
}

Příklad ukazuje stylování nějakého boxíku. Normálně je úzký a má nastaveno float: right, takže zbytek stránky ho obtéká -- to je zapsáno v prvním pravidle bez podmínek. Ale pokud šířka okna klesne pod 414 pixelů (šířka širokých telefonů), pravidlo max-width je splněno a nová hodnota pro obtékání je none, takže se boxík obtékat nebude. Pravidlo se šířkou je zapsáno pomocí max-width, což znamená, že šířka okna musí být maximálně 414px. Bude-li okno širší, vnitřek zápisu @media se neuplatní.

Media podmínka se dá použít i v HTML zápisu. Pokud se má styl z externího souboru použít pouze někdy, uvede se vhodná media podmínka v atributu media v tagu <link> nebo <style>:

<link rel="stylesheet" media="(max-width: 414px)" href="mobilni.css">

Příklad kombinace podmínek

@media (min-width: 500px)
    AND (max-width: 600px) {
       
        body {margin: 0px auto}
   }

Pokud potřebuji pravidla aplikovat jedině při současné platnosti vícero podmínek, existuje na to logická spojka AND. V tomto příkladu chci, aby šířka (width) byla alespoň 500px a zároveň aby nebyla větší než 600px. V takovém případě pak bude mít tag body automatické horizontální okraje (v podstatě bude vystředěn, což v tomto příkladu není důležité). Kdybych pořeboval více podmínek, přidám další AND a třetí závorku.

Modernější zápis podmínky podle šířky

Podmínky z předchozích příkladů půjdou v budoucnu (asi od roku 2023) zapsat i jednodušeji takhle:

@media(width => 600px){   ...    }

namísto min-width: 600px

@media (width => 414px)

namísto max-width: 414px

@media (width => 414px) and (width => 556px){ ... }

namísto (min-width: 414px) and (max-width: 556px), případně dokonce totéž ještě stručněji:

@media (414px <= width => 556px) {    ...    }

U tohoto posledního kombinovaného zápisu bych byl opatrný, pokud bych kombinoval více jednotek než jen px. Kdybych třeba kombinoval px a vh, mohlo by se totiž stát, že průnik podmínek bude prázdný.

Já budu za tento jednodušší zápis pomocí operátorů <=, <, > a => moc rád, protože předchozí podmínkování pomocí kryptických max-width a min-width jsem si vždycky musel raději jak debil nakreslit, abych si připomněl, jak přesně min- a max- funguje. Ale je třeba počkat, než si zápis osvojí Safari. V srpnu 2022 to umí Firefox a Chrome 104.

Příklad tisku

p {font-size: 12pt;}

@media print {
    p {font-size: 16pt;}
}

Pokud se stránka tiskne (@media print), bude velikost písma odstavce 16pt. Jinak (třeba na obrazovce) bude mít velikost 12pt.

Další informace o tisku HTML stránek.

Příklad podle orientace zařízení

@media (orientation: portrait) {
    #logo {width: 300px;}
}

Jestliže si uživatel stránku v mobilu prohlíží otočenou na výšku (portrait), bude #logo široké 300 pixelů. Většina počítačů má orientaci na šířku, tedy landscape, a tak pro ně pravidlo platit nebude.

Podle čeho se dá podmínkovat

Osobně se domnívám, že v praxi se dají vhodně použít jenom možnosti použité výše v příkladech: min-width, max-width, print a orientation: landscape.

V roce 2017 ještě nejsou dobře vlastnosti podporované v prohlížečích a zároveň už je dost pozdě, aby byl ještě někdo zvědavý na to, kdy to prohlížeče dodělají.Většina věcí se nedá rozumně používat. Následující přehled tedy berte spíš jako moje poznámky a hrubou příručku, co používat v nouzi. V praxi budeme nadále podmínkovat přes min-width a max-width a tím to skončí. Beztak jde jenom o zajištění, aby se obsah vešel do prohlížeče, takže podmínkovat podle šířky stačí bohatě.

Typy médií

Historicky starší možnost zápisu předpokládala, že se budou dělat různé styly pro různé typy projektorů, telefonů a televizí. V praxi byly ale všechny tyto alternativy požrány responzivním designem, takže se používají pouze relikty.

@media all vztahuje se na všechna média
@media screen vztahuje se na obrazovky, mobily, projektory, televize, tablety atd.
@media speech má platit pro čtecí zařízení, v praxi jsem to neviděl
@media print tiskový výstup

Ostatní hodnoty @media, které můžete někde najít, už jsou historicky znemožněné a zavržené. Konkrétně šlo o hodnoty aural, braille, embossed, handheld (tohle se občas objevuje v příkladech), projection, tty a tv.

Kromě toho se dají média ještě logicky negovat pomocí not, což je ale v praxi k ničemu, protože jsou typy médií jen 3. Maximálně by se dalo použít toto pro vyloučení tisku, ale v praxi je opět jednodušší napsat @media screen než toto:

@media not print {...}

Navíc si stále nejsem jistý, zda operátor not funguje v Chrome (pozn. 2019).

Vlastnosti médií (media queries)

Mnohem zajímavější než typ média jsou jeho vlastnosti. Je jich spousta, většina jich je na nic.

Velikosti do @media queries mohou být zadávány v pixelech, milimetrech a v em.

Rozměry okna prohlížeče
Vlastnost @media význam vlastnosti
width šířka v různých jednotkách, přesná hodnota
height výška v různých jednotkách, přesná hodnota
max-width prohlížeč je užší nebo stejně široký než zadaná hodnota
max-height prohlížeč je nižší nebo stejně vysoký jako zadaná hodnota
min-width prohlížeč je širší nebo stejně široký než zadaná hodnota
min-height prohlížeč je nižší nebo stejně široký jako zadaná hodnota

Proč píšu, že šířka a výška můžou být v různých jednotkách? Protože to tak je. Skutečně se dají porovnávat například v pixelech, milimetrech nebo em.

Osobně mám docela problém uvědomit si, co znamená max-widt a min-width. Mám s tím dva problémy:

  1. Jednak mě štve, že se pro @media podmínky používají stejné zápisy, jako CSS vlastnosti min-width a max-width, i když s těmito vlastnostmi nemají nic společného.
  2. Vždycky mám problém si uvědomit, co vlastně se porovnává s čím a co má být větší. Musí se to brát doslovně. Max-width doslova znamená, že skutečná šířka okna je maximálně (nejvýše) ta zadaná v podmínce. Min-width znamená, že šířka okna je minimálně (nejméně) ta zadaná.

Další vlastnosti, které se týkaly nikoli okna, ale celého zařízení, jsou takové, které obsahují "device". Osobně je doporučuji nepoužívat, protože v praxi stejně jde hlavně o to, kde se může vykreslovat obsah, ne o nějaké lišty kolem. Pro pořádek jde o tyto vlastnosti: device-aspect-ratio, device-height, device-width, max-device-height, max-device-width,  min-device-width a min-device-height.

Poměry rozměrů okna prohlížeče
Vlastnost @media hodnoty význam vlastnosti
aspect-ratio Zlomek ve formě A/B, kde B je zpravidla 1000. Např. 1336/1000 nebo 695/1000 Poměr výšky prohlížeče ku šířce prohlížeče.
max-aspect-ratio číslo @media pravidlo se vyhodnotí, pokud bude poměr stran nejvýše zadané číslo - spíše vybere užší prohlížeče.
min-aspect-ratio číslo Poměr stran musí být nejméně zadané číslo. Spíše vybere širší prohlížeče
orientation portrait | landscape Portrait = na výšku, landscape = na šířku. Vyhodnocuje se pravděpodobně porovnáním aspect-ratio s hodnotou 1.
device-aspect-ratio Zlomek, např. 9/14 Poměr šířky obrazovky zařízení k výšce obrazovky zařízení.

Pro pořádek uvádím, že ještě existují max-device-aspect-ratio, min-device-aspect-ratio, ale s jejich budoucí podporou si nejsem jistý.

Vlastnosti rozlišení, vykreslování a ovládání
@media hodnoty poznámka
resolution dpi, ve Firefoxu 96dpi, v Edge 100dpi rozlišení v DPI, což je počet podů na palec. Případná hodnota dpcm není podporovaná v Exploreru. Špatně podporovaná vlastnost v Safari, kde vrací nulu, takže je nutno používat -webkit-resolution. Ta ale zase není podporovaná ve Firefoxu.
max-resolution dpi  
min-resolution dpi  
-webkit-device-pixel-ratio číslo, typicky 1 pro počítače a 2 až 3 pro mobily kolik skutečných obrazovkových pixelů se vejde do rozměru 1px. Firefox vrací nulu, Edge patolízalsky implementuje, i když je tam -webkit- prefix. Bez prefixu nefunguje nikde.

Kvůli špatné podpoře mi přijde rozumné @media podmínky založené na resolution nikde nepoužívat. Vídám je v testech pro různá specifická zařízení, ale to je asi jejich jediné použití.

Vlastnosti barev a zařízení
Vlastnost @media Význam vlastnosti
color počet bitů na barvu, typicky 8.
max-color je počet bitů na barvu nižší než zadané číslo?
min-color je počet bitů na barvu větší než zadané číslo?
monochrome na černobílém zařízení vrací nulu, jinak prý počet bitů kódujících šedou barvu. Nedokážu otestovat.
max-monochrome na černobílém zařízení maximální počet bitů, kterými jsou kódovány stupně šedi
min-monochrome na černobílém zařízení minimální počet bitů, kterými jsou kódovány stupně šedi

V různých přehledech vlastností ještě vídám vlastnost color-index, což by mělo odpovídat počtu podporovaných barev. Neviděl jsem ale nikde implementovanou podporu, takže nejde ani podmínkovat pomocí min-color-index a max-color-index.

V nějakém návodu jsem viděl, že existuje také možnost, jak opodmínkovat situaci, kdy si uživatel na svém telefonu nastaví, že nechce moc problikávání. Pak mu lze například vypnout animace:

@media (prefers-reduced-motion: reduce) {
    .animation {
        animation: none;
    }
}

Prefers-color-scheme

Uživatel může mít v operačním systému nastaveno, že preferuje tmavý režim. Tomu se lze přizpůsobit nastavením jiných barev webu. Třeba takhle:

@media (prefers-color-scheme: dark) {
    body { background-color: black; color: white; }
    a:link {color: yellow;}
    a:visited {color: orange;}
 }

Funguje to zhruba od léta 2019. Podstatné v tom zápisu je samozřejmě to prefers-color-scheme: dark.

Budoucí možné podmínky pro @media

Existuje cosi jako návrh Media Queries Level 4. Obsahuje vtipné nápady, podle jakých vlastností zařízení by se daly měnit vzhled a chování stránek. Implementováno z toho ale není (myslím) nic, takže spíš pro zajímavost:

další vlastnosti @media, 2017 nepodporované
@media hodnoty poznámka
update-frequency none | slow | fast Jak rychle dokáže zařízení reagovat na vstup uživatele.
scan interlace | progressive způsob vykreslování obrázků, postupně, nebo prokládaně - neimplementováno
overflow-block none | scroll | optional-paged | paged pokud se nevejde blokový obsah, může uživatel scrollovat? Neimplementováno.
overflow-inline none | scroll řádkový obsah, který se nevejde, může uživatel scrollovat? Neimplementováno.
inverted-colors none | inverted používá zařízení invertované barvy? V takovém případě by bylo například fajn ještě jednou invertovat fotky, aby byly zase normální.
pointer none | coarse | fine přesnost klikacího vstupu
hover none | hover umožňuje zařízení, aby se po něčem přejelo "myší"? Například smartphony žádný hover efekt neumožňují.
scripting none | initial-only | enabled Některá zařízení nepodporují javascript, jiná jenom při vygenerování stránky a potom už ne, jiná i potom.

@supports

Docela užitečné podmínkování se dá udělat pomocí pravidla @supports. Nepatří to do @media podmínek, ale když už píšu o podmínkování v CSS, tak to sem patří.

Příklad:

@supports (display: inline-block) {
    div.fotka {
        display: inline-block; margin: 0px; border: none;
    }
}

Vysvětlení příkladu. Pravidlo @supports se ptá, zda prohlížeč podporuje hodnotu inline-block u vlastnosti display. Pokud ano, nastavuje mu display: inline-block, ale taky mu vynuluje margin a border. Důležité je, že ten margin (nebo cokoli jiného) se dá nastavit na základě toho, zda prohlížeč podporuje nebo nepodporuje inline-block. Dříve se takové chování dalo udělat prostě zápisem

div.fotka {
        display: inline-block; margin: 0px; border: none;
}

ale chování by v takovém případě bylo odlišné. Starší prohlížeče by margin a border vynulovaly i v případě, že se jim nepovedlo nastavit display: inline-block.

Pamatujte, že @supports bude správně fungovat jenom v prohlížečích, které samy @supports umějí. To jsou ale dnes (2019) skoro všechny kromě starého Internet Exploreru a občas nějakých divných mobilních browserů. Přesto z toho plyne, že je lepší psát @supports pravidla tak, aby se to ve starém IE nerozpadlo. Sám už IE nemám, takže to nemůžu otestovat.

Vtipná je také možnost otestovat, jestli prohlížeč podporuje nějaký selektor. Dělá se to prý zápisem

@supports selector(A+B){...}

 

Publikováno 31. 1. 2017, aktualizace 19. 4. 2019

 

Reklama

www.webhosting-c4.cz, extra rychlý SSD webhosting s doménou v ceně
o tvorbě, údržbě a zlepšování internetových stránek

Návody HTML CSS JavaScript Články Ostatní

CSS kurz Přehled hodnot Vlastnosti CSS příklady

Jak psát web píše Yuhů, Dušan Janovský. Kontakt.