Lazy loading - odložené načítání obrázků

Lazyloading v HTML - Historické pokusy o lazyloading - Javascriptový lazy loading - Opožděné načítání iframe

Nejrozšířenější prohlížeče od jara 2020 podporují odložené načítání obrázků pomocí jednoduchého atributu loading="lazy".

Říká se tomu anglicky "lazy loading", občas se to píše dohromady jako "lazyloading" a do češtiny by se to snad dalo přeložit jako líné nahrávání.

Zápis v HTML vypadá takhle jednoduše:

<img src="obrazek.jpg" loading="lazy" alt="obrázek načtený dle potřeby">

Důvod, proč řešit odložené načítání obrázků, je zejména zbytečný přenos dat. Obrázky jsou zpravidla datově nejobjemnější objekty na stránkách. Pokud se nikdy neviděné obrázky vůbec nebudou přenášet, může to znamenat velkou úsporu, která se projeví hlavně při pomalejším spojení nebo při připojení účtovaném za přenesená data (FUP na mobilech).

Lazyloading v HTML

Lazy loading zapsaný takto jednoduše v HTML se nazývá nativní lazy loading, protože je podporovaný prohlížečem přirozeně (tedy nativně), aniž by se něco muselo skriptovat nebo nastavovat.

Ještě jednou připomenu kód.

<img src="obrazek.jpg" loading="lazy" alt="popisek">

Atribut loading má i jiné hodnoty než "lazy", ale ty nejsou tak zajímavé:

loading=  
lazy Nestahuj obrázek, stáhni ho jenom, až bude vidět
eager Stáhni obrázek ihned a s co nejvyšší prioritou
auto chovej se jako dřív, tedy jako by žádný loading nebyl zadán

Podpora atributu loading je zatím omezená na Chrome, Operu a Firefox, což je ale dost dobré, protože se to tím pádem týká asi tří čtvrtin všech uživatelů. Zbylé čtvrtině se obrázky načtou ihned, ale předpokládám, že se podpora do budoucna zvýší. Chrome lazy loading podporuje od srpna 2019 a Firefox od dubna 2020. Už to umí i Edge od verze 79. Safari to zatím neumí.

Jak hluboko pod obrazovkou obrázky musejí být, aby se už načítaly nebo ještě nenačítaly? V prohlížeči Chrome je to od července 2020 1250 pixelů (2500 pixelů na pomalém připojení). Dříve to bylo podstatně více (3000 a 4000 px), což bylo opravdu docela hluboko (asi pět obrazovek dolů), což mimo jiné vedlo k tomu, že se to blbě testovalo. Firefox má hranici hned po spuštění velmi blízko okraje obrazovky a dokonce se mi stalo, že jsem viděl probliknutí při načítání obrázku.

I tak jsem nastavil loading="lazy" u většiny obrázků na svých webech. (Na webu jakpsatweb.cz ne, aby to nenarušilo pochopení příkladů.)

Jak testuju lazyloading

Otevřu si v prohlížeči DevTools (F12), přepnu se na kartu Network a načtu stránku s obrázky s loading="lazy". Podívám se, které se stáhly. Pak si stránkou roluju a dívám se doprava, které se dotahují. Typicky je dobré dělat to na nějaké stránce s mnoha obrázky, takže já na to používám nejčastěji svoje různé galerie obrázků rostlin. testování stahování obrázků přes lazy loading a dev tools v prohlížeči Chrome

Historické pokusy o lazyloading

Je pro mě skoro neuvěřitelné, že se jednoduchý a použitelný HTML atribut na lazyloading objevuje až v roce 2019, ačkoli potřeba něčeho podobného tu byla od začátku webu. Nedalo se to ale snadno řešit, protože prohlížeče jsou odnepaměti slušně vychované tak, že když vidí obrázek, tak ho hned stáhnou. Zpomalit je v tom mohla jenom vnitřní omezení počtu stahovaných objektů z jednoho serveru. Typicky jich prohlížeč stahuje najednou nejvýše šest a sedmý musí počkat, než nějaký dřívější dorazí. Toto omezení pro HTTP 1.1 stále platí (ale ne pro HTTP 2), ale nijak zvlášť zrychlení ani snížení množství dat nepomáhá, protože po prvních šesti si prohlížeč hned požádá o dalších šest.

Občas se může stát, že někdo roluje rychleji, než se obrázky stíhají stahovat, takže může mít pocit, že se mu obrázky donačítají podle toho, jak roluje. Ale to je jen klam daný tím, že se obrázky načítají v pořadí, v jakém jsou uvedeny v HTML kódu stránky, takže ty nižší dorazí později. Případně může mít uživatel slabý hardware, takže se mu již načtené obrázky nestíhají vykreslovat. Nic z toho není ale lazyloading. Obrázky se vždy stahovaly všechny, jakmile je prohlížeč uviděl v html kódu, bez ohledu na velikost monitoru nebo na chování uživatele. To ale může být hodně zbytečně přenesených dat.

Málo rozšířené prohlížeče Internet Explorer a Edge implementovaly svůj vlastní přístup, atribut lazyload (bez hodnoty nebo s libovolnou hodnotou). Ostatní prohlížeče se nepřidaly. Dnes (2019) nemá smysl tenhle atribut používat, protože nejnovější Edge už ho taky nepodporuje.

Kolem roku 2014 jsem zaznamenal první funkční řešení odloženého načítání v javascriptu a časem se jich objevilo hodně. Typický javascriptový kód při lazyloadingu kontroluje, jak uživatel na stránce scrolluje. Spočítá si také souřadnice obrázků ve stránce a porovnává, jestli už je čas obrázek načíst. Obvykle to jsou velmi chytré javascriptové knihovny, které se časem hodně zlepšily, zejména díky tomu, že jim to prohlížeče usnadnily APíčkem intersection observer, které říká, který objekt je ze stránky zrovna vidět.

Potřeba lazyloadingu se promítla i do konstrukce jazyka AMP. V AMP se obrázky namísto tagu <img> vkládají tagem <amp-img>. Důvodem je, aby se v případě přednačítání na <img> obrázky prohlížeče nevrhly a nezačaly je hned stahovat, což by přednačítání neúnosně zdražilo. Proto jsou v kódu obrázky povinně uvedeny jako <amp-img>, aby se daly AMP stránky přednačítat bez obrázků.

Zdaleka nejlepší český článek o lazyloadingu v javascriptu napsal Martin Michálek. Nově do něj na začátek doplnil i informace o nativním lazylodingu, který probírám v tomto textu.

Pro mnoho autorů webu jsou javascriptové knihovny na lazy loading dokonalým řešením. Pro mě ne, vysvětlím proč.

Javascriptový lazy loading

Aby fungoval javascriptový lazyloading, musí se napřed prohlížeči při načtení stránky zabránit, aby obrázky ze serveru načetl. To se ale nedá udělat nijak snadno. Jak jsem zmínil, prohlížeč chce vždy ihned stahovat všechno, co je obrázek, tedy co je tag <img> s atributem src.

<img src="něco.jpg">

Aby se takový obrázek nestahoval, je tedy potřeba tenhle zápis nějak v HTML poničit. Když se neponičí už v HTML, tak se obrázek hned stáhne, což při lazyloadingu nechci. Jsou zhruba dva způsoby ničení HTML obrázků. Buďto se místo img dá něco jiného, nebo se místo src dá něco jiného. Příklad poničení tagu img:

<blabla-img src="něco.jpg">

v praxi nejčastěji

<amp-img src="něco">

Nebo příklad poničení atributu src:

<img blabla-src="něco.jpg">

v praxi nejčastěji

<img data-src="něco.jpg">

Javascriptový lazyloading potom funguje následujícím způsobem:

Proč nepoužívám javascriptový lazyloading

  1. Nemám rád rozbité HTML. Nikdy nevíte, jakým způsobem bude klient stránky číst. Je možné, že bude mít funkční javascript z roku 2019, ale taky je možné, že ho mít nebude. Určitou náplastí je dát za poničený obrázek do HTML kódu stejný neponičený obrázek do <noscript>, což se i doporučuje, ale z mého pohledu to jenom smutně nafukuje kód.
  2. Jistá lapálie z toho vzniká pro indexovací roboty, kteří se snaží indexovat obrázky. Nutno říct, že už si na tyhle zmršené zápisy obrázků roboti museli zvyknout, takže tenhle argument není tak důležitý, ale ještě si nezvykli všechny a dobře. Poničené obrázky prostě občas zůstávají neviditelné.
  3. Je celkem obtížné zadávat tyhle poničené konstrukce prostřednictvím dnešních editorů a starších řešení redakčních systémů, které na něj nejsou připravené. (Oproti tomu přidat jeden atribut taková práce není.)
  4. Neznám žádné javascriptové řešení lazyloadingu, které by fungovalo perfektně. Částečně se to lepší tím, jak přicházejí lepší a lepší prohlížeče. Stále ale zůstává nutnost načítat do stránky javascriptové knihovny a řešit jejich aktualizace.
  5. Hlavně to už ale javascriptem dělat nemusím, jde to přes loading="lazy" přímo v HTML. Což je i hlavní poselství téhle stránky.

Pokud přesto všechno chcete javascriptový lazyload použít, určitě po webu najdete tisíce různých řešení. Třeba budete mít štěstí a bude vám to fungovat dobře. Pravděpodobnější ale je, že to bude chybovat, ale nebudete o chybách vědět. Pokud si mohu dovolit doporučení, tak se prosím zaměřte na řešení využívající Intersection Observer, ta bývají nejlepší.

Opožděné načítání iframe

Iframe má od roku 2019 stejný parametr loading s hodnotou lazy.

<iframe src="adresa-stranky.html" loading="lazy">

Použití je podobné jako u obrázku. Pokud chci do stránky vložit iframe, který uživatel uvidí až po rolování, je lepší ho nenačítat hned a načítání pomocí loading="lazy" odložit, než se k němu uživatel dostane. Řekl bych, že to je ještě užitečnější než v případě obrázků, protože přes iframe se načítá celá stránka se všemi svými dalšími objekty (skripty, styly, obrázky).

Naneštěstí v praxi se iframe používá hlavně pro počitadla a reklamu. Reklamní frikulíni dostávají infarkt z představy, že by se reklama mohla nenačíst, když už ji prodali. Je jim jedno, že uživatel reklamu načítá zbytečně, i když ji stejně neuvidí. Naopak vyžadují (z mého pohledu nešťastně) nastavit reklamě loading="eager", aby se načetla určitě a prioritně.

Opožděné vykreslování částí stránek

Na to překvapivě existuje CSS vlastnost. Část stránky, u které je dobré nevykonávat skripty a renderovat ji, dokud není vidět, se označí a nastaví se jí CSS vlastnost content-visibility: auto. Tato hodnota auto zařídí, že se část stránky vykreslí, teprve, když na ni uživatel doroluje. U dlouhých stránek to může šetřit čas, procesor, baterii atd. Funguje to od Chrome 85. Sám jsem s tím zatím neexperimentoval, ale už se na to těším.

 

Psáno v srpnu 2019, publikováno 21. 12. 2019, aktualizace 23. 7. 2020

 

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í

Články Katalog zdrojů SEM SEO

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