Lazy loading obrázků
Načtení obrázků, až když je na ně odrolováno. Různé postupy řešení.
V případě, že je na stránce hodně obrázků, které nejsou ihned po příchodu na stránku vidět, jsou tzv. pod ohybem, může být rozumné je načítat až v momentě, kdy na ně návštěvník odroluje.
Sníží se tak objem přenesených dat i počet HTTP spojení.
Postup
Jak zmíněné načítání při odrolování vytvořit v JavaScriptu:
- Obrázky mimo viditelnou oblast stránky se po načtení skryjí.
- Při rolování (
window.onscroll
) se zkontroluje, které obrázky mají být vidět, a zobrazí se (donačtou se).
Skrytí obrázku
První zádrhel je v tom, že skrytí přes display: none
nestačí, tj. něco jako:
<img src='obrazek.png' style='display: none'>
Sice obrázek skryje, ale fysickému stažení obrázku nezabrání. Naštěstí ale existují další postupy, jak načtení opravdu zabránit:
Obrázku dát prázdný/nesmyslný atribut
src
a ten skutečný až v momentě, kdy se na obrázek odscrolluje. Původnísrc
může být v nějakém vlastním atributu, ze kterého se hodnota skriptem přesune.Vložit obrázek jako CSS pozadí.
<div class='obal-obrazku' style="display: none"> <div style="width: 100px; height: 100px; background: url(obrazek.png)"> </div <div
Tady už
display: none
zafunguje a obrázek se automaticky nenačte.Důležité ale je
display: none
přidat rodiči<div>
u sbackground
obrázkem. Jinak se i tak v některých prohlížečích obrázek stáhne (test s rodičem / elementem s pozadím).-
Použít značku
<noscript>
. Její obsah se při zapnutém JS nevyhodnocuje. Nevýhoda je, že v IE 7 se z ní nedá přečístinnerHTML
. I tak ale jde přečíst hodnotu<noscript>
atributu, což pro uložení adresy obrázku k pozdějšímu načtení může stačit (ukázka).Hotové řešení založené na jQuery, které využívá tuto techniku.
- Vypsat kolem obrázku JavaScriptem značku
<script>
s neznámým MIME typem. Prohlížeč takový kód nevyhodnotí, ale jeho obsah půjde spolehlivě vydolovat zinnerHTML
(ukázka). Použít značku
<template>
. Ta zatím ale nefuguje v žádném IE, jen v Chrome a Firefoxu.
Konkrétní volba řešení by měla záviset na požadavcích, zejména s ohledem na vyhledávače:
- První a druhá možnost obrázky pro roboty v podstatě zneviditelní. Proto je vhodná jen v případě, že to nevadí / vyhledávač se může k obrázku dostat někde jinde.
- U značky
<template>
není jasné, jak se k ní budou v budoucnu roboti chovat. Zatím je ale Googlem indexována. - Vypsání
<script>
u z neznámým MIME typem je značně nestandardní.
Hotové řešení
HTML
<div class="img">
<script>document.write("<script type='text/lazy-loading'>")</script>
<img src="obrazek.png" width="100" height="100">
<script>document.write("<\/script>")</script>
</div>
JS
var lazyImages = [];
function inViewPort(img) {
var coords = img.getBoundingClientRect();
return (coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight);
}
window.onload = function () {
var imgArea = document; // kde se obrázky hledají
var images = imgArea.getElementsByTagName("div");
for (var i = images.length - 1; i > 10; i--) {
if (images[i].className != "img") continue;
lazyImages.push(images[i]);
}
}
window.onscroll = function() {
for (var i = lazyImages.length - 1; i >= 0; i--) {
if (inViewPort(lazyImages[i])) {
var hiddenCode = lazyImages[i].getElementsByTagName("script")[1];
if (hiddenCode) {
lazyImages[i].innerHTML = hiddenCode.innerHTML;
}
lazyImages.splice(i, 1);
}
}
}
Alternativní řešení
Problém výše uvedeného postupu může být v tom, že při jakémkoliv rolování se budou vždy procházet všechny obrázky a bude se kontrolovat jejich posice a zda jsou vidět (funkce inViewPort
).
Pokud by to stránku zpomalovalo, nabízí se si při načtení a změně rozměrů stránky ukládat posici obrázků.
Ještě mě napadl jeden postup. K obrázkům vytvořeným jako CSS pozadí uložit jejich přibližnou posici do CSS třídy (zaokrouhlenou třeba na stovky — například top-2000
pro obrázky, co jsou přibližně 2000 pixelů od začátku stránky). A při rolování vytvořit skriptem CSS, které obrázek/obrázky s danou třídou zviditelní.
Něco ve smyslu:
pridatCss(".top-" + zaokrouhlit(odrolovanoShora + vyskaOkna) + " {display: block}");
Odkazy jinam
- be]Lazy.js – miniaturní knihovna pro lazy loading obrázků; skutečný
src
obrázku maskuje dodata-atributu
- Unveil – lazy loading plugin pro jQuery/Zepto
Komentáře