Hogyan töltsük be a képeket reszponzív designhoz
Ha valaki készített már reszponzív designt, illetve weboldalt, akkor bizonyára találkozott azzal a problémával, hogy sokszor feleslegesen töltet le nagy képeket (akár CSS, akár nem) egy – akár – mobilon is megjeleníthető oldalon is. Egy kis átgondolással és Javascript-tel csodákat művelhetünk.
A probléma gyökere
Picit még magnál a problémánál maradva, arról van szó, hogy egy reszponzív oldalra tervezett kép, akár 3-4 méretben is megjelenhet, sőt fluid-responsive oldalon, akár ennél több méretben is megjelenhet. Ezzel az a gond, hogy betöltetjük a mobilos felhasználóval is azokat a nagy képeket, amiket ő gyakorlatilag nem lát. Ez ugye a mobilosoknál plusz probléma, hiszen sokaknak van havi letöltési korlátja, nem beszélve arról, hogy eleve gyorsabb lesz az oldalunk letöltése.
A reszponzív designoknál azért alakult ki (vélhetőleg), a fent vázolt probléma, mert a tervezés a nagyobbtól a kisebb felé tart, vagyis a desktop (asztali monitorok) méretekre tervezik meg először a kinézetet, majd ezt viszik tovább, lefelé tabletre, majd mobilra. Így elsőnek a programozó is a nagyobb méretű képekkel fog dolgozni és halad a kisebb méretek felé, jó esetben. Ez egyébként több diszfunkcionális és áttekinthetőségi problémához is vezet, leginkább a kisméretű megjelenítőknél.
Hogyan optimalizálhatunk, a már meglévő honlapokon?
Ha már egy meglévő oldalt kell javítani, akkor is van két lehetőségünk és nem kell újra tervezni semmit. Az egyik megoldás a mára már ismert @media-queries CSS-ben, a másik egy Javascriptes kép betöltési technika megjelenítési mérettől függően. A kettő természetesen (sőt) használható együtt is.
Elegendő-e a @media-queries adta lehetőség reszponzív képek megjelenítésekor?
Alapvetően igen, de valójában mégsem, hiszen a dinamikus megjelenő képeket nem CSS-ből határozzuk meg, mint például egy webshop termékképeit. Hiszen a megjelenő tartalom dinamikus, különböző feltételektől függ. Szemben a statikusnak mondható design elemekkel. Ezért érdemes a két említett technikát ötvözni, és a dinamikusan megjelenített képeket (<img..>) Javascripttel utókezelni.
A tévhitekkel ellentétben, ha CSS-vel határozzuk meg egy elem háttérképét és azt @media-queries-vel több felbontásra is megadjuk, akkor csak a betöltéskor adott mérethez igazítottan tölti le a böngésző a képet. Tehát, ha 4 felbontásra készült @media-queries, akkor is a letöltéskor, csak az adott felbontáshoz tartozó képet tölti le a böngésző, természetesen, ha átméretezzük a böngészőt, akkor már az újszabálynak megfelelő kép is letöltődik. Ez történhet például tabletnél (vagy akár mobilnál is), ha elforgatjuk fekvőre a kütyüt.
Hogy működik a reszponzív kép betöltés javascripttel?
Viszonylag egyszerű a javascriptes kép betöltés megoldása. Alapvetően két látogató csoportra kell gondolnunk, egyik a javascript futtatásra képes böngésző csoport (tipikusan a felhasználók), a másik csoport, akik javascript futtatási lehetőség nélkül böngészik a honlapunkat, ők általában a keresőrobotok (GoogleBot és társai).
A nem javascriptes csoportot az egyszerűbb kiszolgálni, nekik egy <noscript></noscript> tag-ek közé helyezett képet teszünk, alt és title attribútumokkal ellátva a SEO kedvéért.
A célközönség pedig valójában nem <img… /> tag-ben kapja a képet, csak egy <span…> elemet kap, ami tartalmazza data attribútumokban a reszponzív képi tulajdonságokat. Bonyolultnak tűnhet, de egyáltalán nem az.
Hogyan néz ki a javascriptes megvalósítása a reszponzív kép betöltésnek?
A legegyszerűbb, ha mindjárt megnézzük, hogyan is van a kód elkészítve. A HTML résszel kezdjük, amiben látható is a <span> és <noscript> elem, a <noscript> ugye tartalmazza azt a képi megjelenést, amit egyébként is biztosítanánk alapesetben. A <span> pedig data tulajdonságokban tartalmazza a megjelenítéstől függő képek adatait.
<span alt="a kép leírása SEO stb szempontból" data-respimg="true" data-small="image_small.jpg" data-medium="image_medium.jpg"></span>
<noscript><img src="image_medium.jpg" alt="a kép leírása SEO stb szempontból" /></noscript>
Röviden a <span> tuladonságairól:
- alt: A megjelenítendő kép majdani alt tulajdonsága
- data-respimg: Ez mutatja a scriptnek, hogy ezzel a <span> elemmel majd dolgozni kell
- data-small: A megjelenítendő kép kisméretű forrása
- data-medium: A megjelenítendő kép nagyméretű forrása
A javascript kód, ami a képcserélgetést végzi:
// az aktuálisan betöltött kép méret
var _respImgCurrentSize = '';
// a képet méretei felbontásokhoz igazítva
var _respImgSizes = new Object();
// 320px szélesség alatt small
_respImgSizes[320] = "small";
// 320-640px között medium
_respImgSizes[640] = "medium";
// a betöltött képek objektuma
var _respImgHolder = new Object();
// átméretezéskor megvizsgáljuk kell-e képeket cserélni
$(window).resize(function() {
respimg();
});
// az oldal betöltésekor is megvizsgáljuk kell-e képeket betölteni
$(document).ready(function(){
respimg();
});
// a képek cseréje, felbontástól függően
function respimg(){
// aktuális felbontás lekérdezése
var w = $(window).width();
// alap kép méret meghatározása
var size = 'medium';
// megnézzük melyik képméretet kell használnunk
$.each( _respImgSizes, function( key, value ) {
if (w <= key){
size = value;
return false;
}
});
// ha a használandó képméret az aktuális akkor nem kell semmit sem tenni
if (_respImgCurrentSize == size) {
return false;
}
// beállítjuk az aktuális képméretet
_respImgCurrentSize = size;
// az érintett span elemek elemzése
$("span[data-respimg]").each(function(){
// lekérdezzük a megfelelő méretű kép forrását
var src = $(this).data(size);
// lekérdezzük a leendő kép alt tulajdonságát
var alt = $(this).data('alt');
// ha még nem töltöttük le az adott képet, az az nem készült még objektum belőle, akkor elkészítjük
if (typeof _respImgHolder[src] == "undefined") {
_respImgHolder[src] = new Image();
// kép forrásának beállítása
_respImgHolder[src].src = src;
// kép alt tulajdonságának beállítása
_respImgHolder[src].alt = alt;
}
// a span elemben elkészítjük a kép elemet
$(this).html(_respImgHolder[src]);
});
return true;
}
A script jQuery-t kíván, természetesen, aki akarja natív javascriptben is megírhatja. Különösebben nem kívánom ecsetelni a scriptet, inkább jól tele kommenteztem.
A lényege, hogy a megadott <span> elemeket végignézi és az aktuális böngésző mérettől függően lecseréli a benne lévő képeket. Mivel minden kép, amit betölt, eltárolja egy objektumban, ezért minden képet maximum egyszer tölt le, utána csak az objektumból cseréli őket. Valamint érdemes lehet egy data-default értéket is felvenni és beépíteni a scriptbe, így minden képnek egyedileg megadható az a mérete ami alapértelmezett.
Természetesen a kép egyéb tulajdonságait is át lehet vinni az alt-hoz hasonlóan, ez már rajtunk múlik.
SEO szempontból a <noscript>-ben lévő <img> ugyanúgy teljesít, mint a normál, hiszen a robotok javascript nélkül pásztáznak.
Ezzel a technikával jelentős méretcsökkentést és sebesség növekedést érhetünk el.
Remélem mindenkinek sikerül jól implementálnia a példát! :)