O webu
Kdy začne stahování <img> obrázku
<img style="display: none" src="obrazek.png">

Stáhne se neviditelný soubor s obrázkem, nebo ne?

A co takto jako CSS pozadí?

<div style="background: url(obrazek.png); display: none">
</div>

Chování CSS backgroundu se liší napříč prohlížeči (viz níže). Všechny prohlížeče se ale shodují v tom, že obrázek ve značce <img> se stáhne vždy. I když je skrytý přes CSS display: none.

Je tomu tak nejspíš proto, že se prohlížeče snaží pro rychlejší načítání stahovat externí objekty co nejdříve. Tedy už v případě, kdy dorazí HTML kód.

Pokud by se <img> s display: none neměl stahovat, musel by se nejdříve vyřešit jeho styl. To by znamenalo počkat na stažení CSS souborů a i blokujících JavaScriptů, následně by se sestavil CSSOM (CSS Object Model) a až teprve potom by se rozhodlo o stažení obrázku.

Více o vykreslování je v článku:

Prohlížeče tedy raději <img> stáhnou, i když se nakonec nezobrazí.

Ze stejného důvodu rychlejšího startu načítání není nejlepší řešení připojovat *.css a *.js soubory asynchronně JavaScriptem. Prohlížeč tyto soubory nezačne načítat tak brzo, jak by mohl, kdyby byly v HTML. Musí napřed spustit JS kód.

Resource Hints

Pro ještě rychlejší start načítání externích souborů prohlížeče zavádějí tzv. resource hints. Jedná se o zvláštní HTTP hlavičky, které server pošle prohlížeči ještě před samotným HTML kódem.

Prohlížeč tak může začít stahovat požadované soubory ještě před tím, než mu dorazí jediný znak HTML kódu.

Slouží k tomu HTTP hlavička Link s nastavením preconnect/prefetch:

Specifikace počítá ještě s hodnotami dns-prefetch a prerender (renderování stránky dopředu):

Jak zabránit stažení <img>

Tato chytrá vlastnost prohlížečů je značnou překážkou při lazy loadingu obrázků, kdy je potřeba automatickému načtení obrázku zabránit.

Podle mých testů je jediné řešení funkční napříč prohlížeči značka <noscript>:

<noscript>
  <img src="obrazek.png">
</noscript>

Případně tedy nepoužívat <img src>, ale doplnit tuto konstrukci až JavaScriptem, když je obrázek potřeba.

Tímto způsobem se řeší lazy-loading v AMP HTML, kde je pro obrázek zvláštní značka <amp-img>.

Pokusy

Následující pokusy o zabránění selhávají:

  1. Skrytí přes display: none.

  2. Použití značky <template> funguje pouze v Chrome / nové Opeře.

  3. Nestažení obrázku nezabrání ani atribut hidden.

  4. Obrázek se stáhne, i když je nepoužitý uvnitř značky <object>.

  5. Vypsání neexistujícího skriptu skriptem kolem obrázku stažení nezabrání.

Živá ukázka – test pokusů o zabránění načtení obrázku

Stahování CSS pozadí

Internet Explorer, Edge, Chrome a Opera 15+ stahují obrázky i u elementů s display: none.

<div style="background: url(obrazek.png); display: none">
</div>

Soubor obrazek.png z ukázky nebude stažen ve Firefoxu a staré Opeře 12.

Na funkci nemá vliv, jestli je styl obrázku zapsán inline stylem v HTML atributu style nebo přiřazen pomocí třídy.

Obrázky v CSS předpisu pro nepoužité elementy se ale už nestahují vůbec nikde.

.nepouzita-trida {
  /* obrázek se nestáhne, dokud se třída nepoužije */
  background: url(obrazek.png);
}

Obrázek z CSS se stáhne až v momentě, kdy se daný předpis na stránce použije.

Pravidlo @media

Obrázky na pozadí v @media podmínkách se potom chovají jako nepoužité předpisy.

.trida {
  background: url(velky.png);
}
@media (max-width: 50em) {
  .trida {
    background: url(maly.png);
  }
}

Do šířky 50em se stáhne pouze obrázek maly.png, jinak pouze velky.png.

Změna velikosti okna již načtené stránky a aplikování různých předpisů v @media potom teprve vyvolá načtení jiného obrázku z příslušného @media bloku.

CSS sprite v <img>

Zajímavou věc jde pozorovat ve výsledcích vyhledávání na Google.

Google logo je zdánlivě vložené značkou <img>, ale ve skutečnosti se jedná o sprite obrázek:

Sprite obrázků Google

Pomocí posicování a oříznutí je z tohoto obrázku vidět jen samotné logo:

Sprite obrázků Google

Nabízí se vysvětlení, že je to právě kvůli rychlejšímu startu stahování obrázků.