Tündéri manócskák avagy CSS Sprites

css_spritesHallottál már a tündéri CSS manócskákról? Érted őket igazán? A manók igazából nem is olyan picikék, hanem nagyok, pont ez a lényeg. Ezzel a technikával több kisebb képet egy nagyobbal tudsz helyettesíteni és ezután annak csak bizonyos részeit használni épp ott és úgy ahogy a weblap egyes részein kell. A CSS manók legegyszerűbb példája amikor egy gomb normál és benyomott állapotban másképpen néz ki és nem két külön képként, hanem egy képként használjuk őket. Persze ebben az esetben kell egy kis varázslat.

A technika

Ha van egy linkünk és szeretnénk, hogy úgy nézzen ki mint egy gomb, akkor általában egy háttérképet teszünk be mögé CSS-sel, és a benyomott állapotban egy másik háttérképet használunk. Ebben az esetben a CSS-ünk valahogy így néz ki:

#linkgomb{
   background-image: url('sima_gomb.jpg');
}
#linkgomb:hover{
   background-image: url('benyomott_gomb.jpg');
}

Ha a feladatot egy kicsit másképpen közelítjük meg akkor ahelyett, hogy két külön képet használnák, használjunk egyet, aminek a tetején van a sima és az alján a benyomott állapotú kép. Ekkor nem a háttérképet, hanem annak a pozícióját fogjuk módosítani.

#linkgomb{
   background-image: url('nagy_gomb.jpg');
   background-position: top left;
}
#linkgomb:hover{
   background-position: bottom left;
}

Kicsit továbbgondolva az ötletet igazából akár tetszőleges számú képet is összeolvaszthatnánk így eggyé.

Jó ez nekünk?

Épp nemrég károgtam arról, hogy a userek mennyire érzékenyek arra, hogy ha az oldal lassan töltődik be. Akkor nem járnánk jobban több kis képpel mint egy behemóttal? Hát nem feltétlenül.

Egy átlag oldal esetében az oldal letöltési idejéből kb 5-25% a HTMl forrás, a többi 95-75% a többi cucc, azaz a képek, a flash, a CSS, a JavaScript és a többiek. Ennek (a méretek mellett) az az oka, hogy létezik egy fránya limit, miszerint egy webszerver egyszerre csak 2 HTTP lekérést szolgál ki ugyanazon kliens felé. Mivel minden egyes fájl, legyen az maga a HTML, egy kép vagy bármi más külön-külön HTTP lekérést igényel a sebesség növelhető azzal ha az oldal letöltéséhez kevesebb HTTP lekérést kell indítani.

E mellett egy nagyobb kép általában jobban optimalizálható mint több kisebb.

Tegyünk egy próbát!

Íme egy 5 elemű lista úgy hogy a képek váltakozását külön képekkel oldjuk meg.

Mindehhez a következő CSS tartozik.

ul#cssSpritesPelda1{
  list-style-type: none;
  list-style-image:none;
}
#cssSpritesPelda1 li{
  height: 48px;
  background-repeat:no-repeat;
  cursor:pointer;
}
#cSP11{
  background-image: url('http://webmania.cc/static/css_sprites/1.png');
}
#cSP12{
  background-image: url('http://webmania.cc/static/css_sprites/2.png');
}
#cSP13{
  background-image: url('http://webmania.cc/static/css_sprites/3.png');
}
#cSP14{
  background-image: url('http://webmania.cc/static/css_sprites/4.png');
}
#cSP15{
  background-image: url('http://webmania.cc/static/css_sprites/5.png');
}
#cSP11:hover{
  background-image: url('http://webmania.cc/static/css_sprites/1_h.png');
}
#cSP12:hover{
  background-image: url('http://webmania.cc/static/css_sprites/2_h.png');
}
#cSP13:hover{
  background-image: url('http://webmania.cc/static/css_sprites/3_h.png');
}
#cSP14:hover{
  background-image: url('http://webmania.cc/static/css_sprites/4_h.png');
}
#cSP15:hover{
  background-image: url('http://webmania.cc/static/css_sprites/5_h.png');
}

És a következő HTML kód.

<ul id="cssSpritesPelda1">
  <li id="cSP11">Első elem</li>
  <li id="cSP12">Második elem</li>
  <li id="cSP13">Harmadik elem</li>
  <li id="cSP14">Negyedik elem</li>
  <li id="cSP15">Ötödik elem</li>
</ul>

Amint az a CSS-ből látszik 10 különböző képet használtunk amelyeknek a rendkívül fantáziadús 1.png, 2.png, illetve az 1_h.png, 2_h.png stb neveket adtam. Szerintem a 10 kép összesen 46.213 byte és megjelenítésükhöz 10 HTTP lekérés volt szükséges.

Ezután nézzük mi van ha segítségül hívjuk a manót. A manó a behemot.png névre hallgat és 37.252 byte. Mivel egyetlen egy kép megjelenítéséhez csupán 1 HTTP lekérés szükségeltetik. A behemót képünk így néz ki, azaz tartalmazza mind az 5 képünk mindkét állapotát.

Tehát tizedannyi HTTP lekérés és 9KB a behemót javára. 9KB talán első hallásra még nem is tűnik olyan nagynak, de ha egyesével összeadogatom a fájlok méretét akkor az jön ki, hogy az utolsó két teljes méretét megspóroltuk az összevonással. Úgy is mondhatnám, hogy a 10 képből összevont kép kicsit kisebb mint az eredeti képek közül 8.

A HTML kódunkon nem kell semmit igazítani, a CSS-en viszont igen.

ul#cssSpritesPelda2{
  list-style-type: none;
  list-style-image:none;
}
#cssSpritesPelda2 li{
  height: 48px;
  background-repeat:no-repeat;
  cursor:pointer;
  background-image: url('http://webmania.cc/static/css_sprites/behemot.png');
}
#cSP21{background-position: 0 0}
#cSP22{background-position: 0 -48px}
#cSP23{background-position: 0 -96px}
#cSP24{background-position: 0 -144px}
#cSP25{background-position: 0 -192px}
#cSP21:hover{background-position: 0 -240px}
#cSP22:hover{background-position: 0 -288px}
#cSP23:hover{background-position: 0 -336px}
#cSP24:hover{background-position: 0 -384px}
#cSP25:hover{background-position: 0 -432px}

Összegzés

A látvány mindkét esetben azonos. A különbség abban van, hogy az első megközelítéssel több adatot kellett a szervertől letöltenünk és több HTTP kérésre kellett megvárnunk a választ. Az oldal betöltődésének gyorsasága szempontjából a két változat közül a CSS sprites megoldása 9KB-ot és 9 HTTP lekérést spórolt meg, tehát mindenképpen ő a nyerő.

További előnye a CSS manónak az, hogy a kép teljes egészében be fog töltődni az oldallal együtt, így ha a user egyből rámutat a menüre akkor ott a kép szépen meg fog változni. Ezzel ellentétben a több képes megoldás esetében elképzelhető, hogy a többszörös letöltés miatt a kép rámutatáskor villan egyet, mielőtt bejönne a benyomott változata.

A bemutatott példa csak ízelítő a sprite használatához. Nem feltétlenül azonos méretű, illetve azonos helyen használt képek esetében is használható amint azt lentebb a google példájában látni lehet.

Nem csak kliens oldallal nyerünk a manó megtáncoltatásával, mert a kevesebb HTTP lekérés a szerver oldalon is csökkenti a terhelést.

Mennyire biztos a módszer?

Ahhoz elég biztos, hogy használják a Google, a Yahoo és az Amazon főoldalán és aloldalain. Például ha ránézünk a Google oldalán a logóra akkor ezt fogjuk látni.

Játékszerek

A cikkben használt képek egy csomagban: Töltsd le egyben

Lustáknak pedig van online sprites generátor.

22 thoughts on “Tündéri manócskák avagy CSS Sprites

  1. Pingback: Sprites | TCZ

  2. Jóság a CSS prite, az biztos. Eddig mindig csak az összeillő képeket (méret és felhasználás szerint) válogattam össze egy nagy képbe, de most az egyik projektnél megpróbálkozom a Google féle példával (már ahol ez megoldható, mert ha a paddinggal játszik az ember, akkor nem kivitelezhető, vagy csak nagy üres területekkel az összesített képen) .

    Egyébként ez megoldás csak a WEB-en megy újdonságszámba (bár már annyira nem újdonság). Az asztali programoknál 10+ évvel ezelőtt is ezt alkalmazták, pl. játékprogramok grafikájánál.

  3. > egy fránya limit, miszerint egy webszerver
    > egyszerre csak 2 HTTP lekérést szolgál ki
    > ugyanazon kliens felé

    Ez így ebben a formába nem igaz. A böngészőket írták meg úgy, hogy egy domain-re (nem összekeverendő a szerver fogalmával) párhuzamosan csak kettő kérést küldenek el. Nem arról van tehát szó, hogy a szerver buta és nem szolgálna ki többet. A bűvös 2-es szám pedig még a dial-up időkből származik, és minden mai modern böngésző friss verziója már általában 6-tal dolgozik. (IE-szériából majd csak a 8-as verziótól kezdve.)

    http://stevesouders.com/ua/

  4. A CSS sprite technika egyébként akkor lenne igazán űtős, ha CSS-ből nem csak azt lehetne beállítani, hogy hogyan ismétlődjön a háttér, hanem, hogy melyik része legyen az felhasznált háttér. Azaz bal felső, jobb alsó koordinátákat meg lehetne adni.

    Mert ameddig ez nem megoldható, addig nem lehet az ismétlődő háttereket összevonni. Ha ez elérhető lenne, akkor nagyságrendekkel lehetne csökkenteni a kiszolgálandó képek számát.

  5. A spriteot manóra fordítani téves, itt a számítógépes grafikáknál használt ‘sprite’-okra utal. Régen a gépek teljesítményének jobb kihasználását tette lehetővé több kép egy képbe történő összefogása!

  6. Szvsz mindenkinek jó megoldás lehetne, ha az oldalhoz tartozó fájlokat egyben (pl jar-ban) lehetne bekötni. Így egyszerre letölthető, könyebben kezelhető, mint pl a sprite-ok, és nem kell a js-ek, css-ek egyesítésével sem vesződni.

    Egy .tar.gz pl on-the-fly kitömöríthető, azaz az okos browserek még azt sem veszítenék el, hogy amint megérkezett egy kép/css, azt azonnal ráhúzzák az oldalra.

  7. A kérdésem helyesebben:)
    Nem igazán ide tartozik, de azt szeretném megkérdezni, hogy ilyen “kicsit fényes felületű” ikonokat hogy kell készíteni?

  8. Üdv,

    Ez majdnem jó, de pl. az IE6 az csak az “a:hover”-t érti, szóval úgy kell módosítani, hogy nem a “li” tagra, hanem az “a” tagra teszed rá a háttérkép váltást.

  9. Jó cikk!

    Az egyik munkában fordult elő, hogy használni kellett átlátszó png-ket. Használni akartam a sprite technikát, majd gondolva az ie6-ra ráengedve egy kényelmes jquery pngfix-et minden rendben lesz. Sajnos igy nem működik a dolog, pontosabban a háttérpozicionálás. Rákerestem a neten a dologra, de csak olyan undoritó megoldásokat találtam, ahol abszolút poziciókat, clip és filter tulajdonságok… Esetleg valami egyszerűbb megoldás?

  10. Miert szolgalna ki csak kettot? Fiber netes kapcsolatknal aztan nagyon fontos hogy 0,00000001 vagy 0,00000000000001 mp alatt tolt be az oldal

  11. Nem gányolás, csupán tudni kell mit mikor és hol alkalmazz! Nem kell mindent egy képbe belerakni. Már is sokkal jobb, ha nem két külön képet hívsz be egy gombnak, hanem csak egyet. Vagy netán egy egész gomb csoportnak csinálhatsz egy sprite-ot… Gányolásnak sem nevezném. Csak Önmagamat tudom ismételni. Tudd, hogy mikor mit és hol kell használni….

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.