(Snad už) Definitivní responzivní obrázky – srcset a sizes

Před rokem tady Robin Pokorný psal o aktuálním vývoji na poli responzivních obrázků, ukazoval src-N variantu řešení a vyjádřil naději, že se standardizátoři již brzy domluví a hlavně — že přijdou nějaké implementace v prohlížečích.

Pokud jste se také na nějaké řešení těšili a pokud vám doma zbyl po silvestrovských oslavách nějaký sekt, tohle je myslím ta pravá chvíle pro odšpuntování. Máte tu totiž standard, jehož podporu deklarovali všichni významní výrobci prohlížečů a který je s drobným přimhouřením očí s pomocí polyfillu použitelný už dnes.

V responzivním designu často potřebujeme volit mezi různými variantami jednoho obsahového obrázku. Nejčastěji proto, že chceme ušetřit datový objem stránky na mobilech.

Naš starý známý <img> k tomu nestačí. A tak iniciativa Responsive Images Community Group přišla s novými atributy – srcset a sizes – a také s úplně novým tagem <picture>.

Bavíme se tady o bitmapových obrázcích, typicky fotografiích. Pro ikony, logotypy a další vektorový obsah je lepší použít formát SVG nebo alternativu v podobě ikonfontů.

Proč ne <img src=““>?

Občas je pro responzivní obrázky možné vidět řešení s nahrazováním atributu src:

<img src="large.jpg" data-small="small.jpg" …>

JavaScriptem pak na malých displejích zkopírujete obsah data-small do src a prohlížeč zobrazí správný obrázek. Na pohled elegantní, jenže ve výsledku na pytel.

Neexistuje totiž způsob, jak prohlížeč odradit od stažení obrázku nalinkovaného v <img src>. Proto se v těchto řešeních obrázek sice vymění, ale stáhnou se oba soubory, což na pomalé mobilní síti moc nepotěší.

Proč vlastně více variant obrázků?

Holky a kluci v RICG si sedli a vymysleli 9 scénářů, kdy je potřeba jeden obrázek reprezentovat různými variantami. My si tady ale budeme povídat jen o těch nejdůležitějších:

image01

  1. Výběr varianty obrázku podle velikosti okna prohlížeče.
  2. Výběr varianty podle velikosti obrázku v rámci layoutu stránky. V některých situacích totiž můžeme na větším displeji potřebovat menší obrázky. Srovnejte layout pro mobil a tablet na obrázku.
  3. Výběr podle device-pixel-ratio neboli poměru mezi hardwarovým a CSS rozlišením.
  4. Výběr podle art direction, jinak řečeno výtvarné řežie. Typicky když obrázek na mobilu potřebujeme oříznout jinak než na desktopu.

S bodem 4 vám pomůže jen nový tag <picture>, tomu se budeme věnovat v příštím článku. Ve všech ostatních situacích si vystačíte s novými atributy <img> – srcset a sizes. No a o těch si tu budeme dneska vyprávět.

srcset/sizes

Nové atributy elementu <img>, které řeší potřebu autorů stránek zobrazovat v různých stavech responzivního designu různé varianty obrázků.

Na atributech srcset a sizes je hezké, že poměrně složité rozhodování, který obrázek ve které situaci použít, necháváme na prohlížeči. Jako autoři stránky mu jen řekneme, jaké varianty obrázku má k dispozici (srcset) a jak jsou veliké mezi jednotlivými breakpointy layoutu (sizes).

srcset – sada zdrojů obrázku a jejich vlastností

<img src="small.png"
srcset="small.png 600w, medium.png 1024w, large.png 1600w"
alt="Obrázek" width="200" height="200">

srcset demo na CodePen. (V demu jsme použili polyfill Picturefill, takže funguje ve všech prohlížečích, ale možná jste si všimli nepřítomnosti atributu src.)

Prohlížeči tím sdělujeme, že jsme předgenerovali obrázek small.png v šířce 600 pixelů, medium.png v šířce 1024 pixelů a a large.png v šířce 1600 pixelů. V atributu src pak uvádíme fallback pro prohlížeče, které srcset neumí.

Prohlížeč pro rozhodování o tom, který obrázek načíst, zde bere šířku okna. Takže do 600 pixelů a méně širokého okna načte small.jpg, mezi 601 a 1024 pixelů širokým pak medium.jpg a v oknech šířky od 1025 pixelů načte large.png.

Některé prohlížeče – jako Chrome – to budou dělat chytřeji a například small.jpg budou zobrazovat i daleko nad hranicí 600pixelového okna, protože na vizuální kvalitě to obrázku neubere.

Prohlížeč bere v potaz i aktuální device-pixel-ratio, a tak třeba na původním Retina displeji (device-pixel-ratio=2) načte medium.jpg i v případě, že okno je široké 600 pixelů. Chrome například načítá kvalitnější obrázek i ve chvíli, kdy uživatel nad obrázkem zoomuje. Do budoucna prohlížeče mohou načítat třeba méně kvalitní obrázek na pomalém internetovém připojení.

Ano, přesně v potenciálu chytrého rozhodování prohlížeče vězí krása srcset. Prohlížeč zváží všechny informace, které má o stavu stránky k dispozici a podle toho vybere nejvhodnější obrázek. Vy jako autoři jen vygenerujete dost variant a správně je popíšete – pomocí deskriptorů.

Deskriptory vlastností obrázků v srcset

Zatím jsme zmínili jen šířku obrázku – deskriptor w. Ten říká jakou šířku v pixelech obrázek má při exportu z grafického editoru nebo po výstupu z vašeho skriptu.

Druhý deskriptor x určuje připravenost souboru s obrázkem pro různé device-pixel-ratio poměry, například:

<img … srcset="image.jpg, image@2x.jpg 2x">

Tímto zápisem říkám, že image@2x.jpg má prohlížeč použít při device-pixel-ratio alespoň 2 a image.jpg ve všech hodnotách menších než 2.

Pojďme se ale podívat na atribut, který prohlížeči umožní vybírat nejen podle fyzických parametrů souborů s obrázky, ale i podle velikosti obrázku v rámci layoutu stránky — sizes.

sizes – velikosti obrázků

V praxi totiž tak často nepotřebujeme volit obrázek podle šířky okna, ale podle šířky obrázku v rámci layoutu:

<img src="small.png"
srcset="small.png 600w, medium.png 1024w, large.png 1600w"
sizes="(min-width: 768px) 300px, 100vw"
alt="Obrázek" width="200" height="200">

Tímto zápisem říkáme, že responzivní layout je vymyšlený tak, že v rozlišeních nad 768 pixelů má obrázek šířku 300 pixelů ve všech ostatních pak 100 procent šířky viewportu.

První vyhovující varianta v sizes vyhrává, takže na pořadí záleží. Bacha na to.

Nojo, jenže v responzivním, potažmo fluidním layoutu obvykle přesně nevíme, jaké rozměry  budou mít obrázky v rámci konkrétní šířky okna. A hurá — tady přichází síla kombinace sizes s funkcí calc(). Pomocí ní můžeme elegantně definovat velikost obrázku relativně k layoutu mezi konkrétními breakpointy.

Opět tedy máme demo na CodePenu. Nejdříve si ale raději pojďme vizualizovat, jak vlastně náš layout vypadá:

image00

Do 600px breakpointu je to jednoduché – obrázek zabírá celou šířku layoutu. Nikoliv ovšem šířku okna, a tak musíme odečíst výchozí margin u <body>, který mají prohlížeče nastavený na 8px:

calc(100vw - 2*8px)

Od 600px breakpointu pak musíme vyjít z CSS layoutu:

@media only screen and (min-width: 600px) {  
  .image {
    width: 49%;
  }  
}

Přepsáno do funkce calc() to vypadá takto:

calc((100vw - 2 * 8px) * 0.49)

A ještě v prostém jazyce:

(100 procent šířky viewportu - výchozí margin u <body>) * 49% šířka obrázku

Takže celý zápis tagu <img> bude vypadat takto:

<img src="small_600.png"
srcset="small_600.png 600w, medium_1024.png 1024w, large_1600.png 1600w"
sizes="(min-width: 600px) calc((100vw - 2*8px) * 0.49), calc(100vw - 2*8px)"
alt="Obrázek" width="200" height="200">

Pojďme si pro jistotu ještě shrnout zápis v sizes:

  1. na rozlišeních od 600 pixelů bude mít obrázek velikost calc((100vw - 2 * 8px) * 0.49)
  2. ve všech ostatních případech – to znamená do 599 pixelů – pak calc(100vw - 2 * 8px)

srcset & sizes demo na CodePenu. (V demu jsme použili polyfill Picturefill, takže funguje ve všech prohlížečích, ale možná jste si všimli nepřítomnosti atributu src.)

Se srcset a sizes si vystačíte v naprosté většině situací, kdy budete potřebovat sáhnout po řešení responzivních obrázků.

Pokud budete potřebovat servírovat zcela jinak vypadající obrázky pro různá rozlišení (scénář art direction) nebo obrázky v různých souborových formátech, sáhněte po novém tagu<picture>.

Pomocník pro prohlížeč, ne příkaz

Dobré vědět, že srcset, sizes i všechny konstrukce v <picture> jsou jen jakousi nádstavbou nad stále funkční a povinný mechanizmus <img src>. Co uzná prohlížeč za lepší alternativu obrázku v <img src> , tam prostě zkopíruje a zobrazí.

Nevýhody současného řešení

Materiál je to čerstvý, ostatně podpora prvních prohlížečů přišla snad v rekordně krátkém čase po vydání finální verze specifikace. Dále se o něm diskutuje. Proto se nelze divit některým nedořešenostem. Kromě problémů polyfillu je tu například často zmiňovaný fakt, že HTML každého obrázku v sobě nese informaci o nastavení designu. Když se změní, musí chudák vývojář všechny výskyty této informace měnit. Věřím ale, že se tuhle drobnou nevýhodu podaří brzy odstranit. Například přidáním meta tagu, který by informace o layoutu sdružoval na jedno místo.

Podpora v prohlížečích

Prakticky všechny prohlížeče ústy svých tvůrců deklarovaly, že tento standard naimplementují. Ano, včetně Internet Exploreru, ptáte se správně. Jenže jim bude chvíli trvat než to udělají. Nativní podpora je k dispozici v posledních verzích Chrome, Opeře a zčásti Safari. Do té doby – a samozřejmě kvůli starším prohlížečům – je potřeba používat polyfill Picturefill. Ten má jistá omezení, ale ve většině případů vám pomůže s výběrem správné varianty obrázku už nyní, takže se zkoušením není potřeba váhat.

Původně vyšlo na VzhůruDolů.cz. Responzivní obrázky autor také školí na kurzu responzivního designu. Za cenné podněty k materiálu o responzivních obrázcích autor děkuje Robinovi Pokornému, na jehož webu najdete odkazy na přednášky o tomhle tématu.

Komentáře: 8

Přehled komentářů

Robert argument o nahrazení javascriptem je vadný!
Martin Michálek Re: argument o nahrazení javascriptem je vadný!
P4l4din Firefox
P4l4din PS: Firefox
Martin Michálek Re: PS: Firefox
kamienok pouziti s lazy load?
Martin Michálek Re: pouziti s lazy load?
kamienok Re: pouziti s lazy load?
Zdroj: https://www.zdrojak.cz/?p=14144