Martin Michálek Martin Michálek  – 27. 4. 2020

Nedávno jsem na Vzhůru dolů publikoval text o nastavení poměru stran pro obrázky, video, iframy a další obsah vkládaný do HTML zvenčí. Říkejme mu média.

Podívejte se na video „Obrázky (IMG v HTML): Poměr stran jednoduše“.

YouTube: youtu.be/zmkIvMSKU8U

Problém je v tom, že prohlížeče vykreslují stránku dříve než jsou tyto prvky stažené. Pokud neznají velikost ani poměr stran médií, dopadne to tak, že se stránka vykresluje vícekrát. Pro uživatele to znamená nepříjemné „poskakování“ obsahu v momentě, kdy už například čte text.

Před responzivním designem to bylo v pořádku

Jak píše Jakub Vrána v komentářích:

Používat atributy width height jsem doporučoval už před dvaceti lety přesně z tohohle důvodu. To se na to postupně nějak zapomnělo?

Nezapomnělo. Přišel totiž přišel responzivní designpružné obrázky:

img {
  max-width: 100%;
  height: auto;
}

Díky height:auto, které přebilo parametr height z HTML, přestaly být prohlížeče schopné spočítat skutečnou výšku v responzivním layoutu.

Takže uvádět atributy v HTML dříve stačilo, pak díky responzivnímu designu přestalo stačit a dnes prohlížeč mění chování, aby to zase stačil mohlo. A o tom posledním kroku je tento článek.

Takhle to na webech vypadat nemá, ale skoro vždy vypadá:

V původním článku jsme na to šli přes různé hacky a sliboval jsem, že se blýská na lepší časy. Zmiňoval jsem, že to snad bude brzy rovnou vestavěné v prohlížečích.

Ty lepší časy teď přicházejí, protože, jak jste se mohli už dočíst na Smashing Magazine nebo slyšet v podcastu, prohlížeče pro nastavení poměru stran prvků <img> používají (Chrome a Firefox) nebo používat začnou (Safari) atributy pro nastavení výšky a šířky.

Takhle to vypadat má:

Zajímavé je, že nyní jde o řešení přímo na úrovni vykreslování v prohlížeči, takže se nepoužívá původně plánovaná CSS vlastnost aspect-ratio.

Poměr stran obrázku nastavíte atributy widthheight

Aktuální stav si můžeme zjednodušit následovně.

Obrázky

U obrázků prostě vždy vyplňte atributy widthheight u značky <img>:

<img src="image.jpg" alt="…"
  width="640" height="360">

Dále platí:

  • Pokud je obrázek fixních rozměrů, dejte do atributů pixelovou velikost, kterou má zabrat v layoutu.
  • Pokud je obrázek pružný, tzn. má v CSS nastavený atribut width nebo height na hodnotu auto), dejte do atributů poměr stran vycházející z maximální velikosti obrázků v responzivním layoutu.

Pokud vám vadí, že to zatím nefunguje v Safari a starších prohlížečích, je potřeba znát také alternativní metody pro nastavení poměru stran.

Ukázka

Obrázek v následujícím CodePenu má nastaveno zpoždění načítání, takže byste měli vidět nejprve šedivý zástupný symbol. Po čase se vám načte zelený obrázek:

Všimněte si, že v Chrome a Firefoxu vám layout celou dobu drží jako přibitý. No a pak se podívejte, že v CSS pro toto nepoužíváme žádné speciální triky. Prohlížeči prostě stačily atributy widthheight.

Pro pořádek ještě dodám dva jiné CodePeny:

Jaké rozměry dát do widthheight?

Možná vás napadlo, že pokud atributy určují poměr stran, nemuseli byste si s tím lámat hlavu a vložit do nich nějaké nízké číslo, které onen poměr stran vyjadřuje…

<!-- Tohle fungovat nebude: -->
<img src="image.jpg" alt="…"
  width="16" height="9">

…a mě to napadlo určitě, protože přesně takhle elegantně funguje responzivní layout v AMP.

Jenže to fungovat nebude. Pokud do widthheight vložíte menší čísla než je aktuální potřeba layoutu, vykreslí se obrázek ve fixních rozměrech.

Takže vkládaný rozměr musí být rovný nebo větší než je největší rozměr obrázku ve vašich layoutech. Pro zájemce přikládám CodePen tohoto neúspěšného pokusu.

Video a ostatní média

S videem, <iframe> a dalšími externími médii vám zatím prohlížeče nepomohou, takže používejte padding trik nebo jiné alternativní metody pro nastavení poměru stran.

Podpora v prohlížečích

Jak už bylo řečeno, všechny tři dnešní podstatné prohlížeče to umí nebo deklarovaly, že to naimplementují:

Ostatní prohlížeče buď vycházejí z Chrome (Edge, Opera…) nebo jsou pro potřeby článku nerelevantní. V takovém MSIE to už asi nezapnou, na druhou stranu tenhle prohlížeč pozvolna odchází a na zařízeních s pomalým připojení se nevyskytuje.

Problémy a nedořešenosti

Jako každá nová metoda má i tahle zatím své mouchy. Dejte si pozor hlavně v případě použití následujících tří metod.

Art direction

Pokud používáte značku <picture> pro vkládání různě rozměrných obrázků na různých rozlišeních…

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg">
  <img src="small.jpg" alt="…" width="640" height="360">
</picture>

…může vám tato metoda haprovat, protože u alternativních zdrojů uvedených v <source> není možné atributy widthheight definovat. O tom se ale ví a už se to řeší.

Lazy loading obrázků

S nativním lazy loadingem by „nativní poměr stran“ fungovat měl…

<img src="image.jpg" alt="…" loading="lazy"
  width="640" height="360">

…ale je zde jeden bugísek v Chrome, který se hodí sledovat.

Pokud nepoužíváte nativní líné načtení - je potřeba ošetřit přes aspect-ratio a ostatní metody

Související: Lazy loading obrázků a iframe

Nasazení mimo obrázky

A co prvky <video>, <iframe>, <object> a další externí média? Tam by se poměr stran hodil také, že ano…?

Opět jen můžu říct, že se to řeší, ale očekávám, že podobně jako u obrázků se to dořeší jen u videí, protože tam se poměr stran nastavuje podobně jako u obrázků.

Ostatní prvky jsou trochu jiné liga (dokumenty vkládané do dokumentu), takže bychom neměli očekávat podobné chování.

Shrnutí

Prohlížeče se teď tedy v případě značky <img> chovají tak, jak jsme asi dlouho všichni očekávali.

Jak jsem říkal v nedávném podcastu, mnozí z webařů a mnohé z webařek si stavu, kdy byl poměr stran obrázků rozbitý, ani nevšimly. Pro ně se nic nemění.

Pro nás ostatní to znamená, že můžeme z kódu odstranit padding trik a další hacky. Alespoň ve většině případů, protože se bez nich nadále neobejdeme mimo obrázky.

Lidem, kteří nastavují widthheight špatně, tedy ne v souladu s poměrem stran obrázků může tento krok prohlížečů rozbít layout stránky během vykreslování.

No a pro úplně všechny webaře platí – vyplňujme prosím poctivě atributy widthheight<img>.