CSS-sprites

Tradisjonell bruk av grafikk i webdesign

Vanligvis legger man inn grafikk på nettsider ved å bruke en image-tag:

<img src="grafikk.png" width="24" height="24" alt="Grafikk">

Dette er en helt OK måte å gjøre det på, men hvis man har et større nettsted med et stort antall knapper, brytere, ikoner og andre små elementer, så blir det fort veldig mange forskjellige filer som må lastes inn i nettleseren.

Samtidige nedlastinger

Nettlesere har en begrensning som gjør at de bare kan laste inn (laste ned) et visst antall filer fra samme server samtidig. Tidligere har dette vært begrenset til 2 samtidige innlastinger (igjen; nedlastinger) i enkelte nettlesere.

Spre bildene på flere domener

En løsning på dette har vært å spre de forskjellige filene på forskjellige subdomener, slik som gfx1.hardcode.no, gfx2.hardcode.no osv., men det sier seg selv at dette ikke er en god løsning i lengden. Et nettsted som Facebook vil kanskje ha bruk for noen hundre forskjellige ikoner bare for å vise nyhetsfeeden din.

Nytt ikon ved mouseover

Men det finnes også en annen utfordring med mange slike forskjellige bildefiler: La oss si at du har et ikon med litt duse farger, men som skal vises i sterke farger ved mouseover. Dette kan du løse ved å endre CSS ved hover (eller JavaScript og onmouseover). Men det som vil skje i praksis er at ikonet med de duse fargene lastes samtidig som nettsiden, og når du fører musepekeren over ikonet må det lastes inn (ned!) en ekstra fil. Dette kan ta noen millisekunder, noe som gir en dårlig brukeropplevelse: Man fører musepekeren over ikonet, så går det et halvt sekund, og først da skifter ikonet til sterke farger.

CSS-sprites

Eksempel på sprites

Løsningen på disse utfordringene kan være bruk av CSS-sprites.

CSS-sprites går ut på at man setter sammen alle de forskjellige bildefilene til ett bilde. Her ser du et eksempel med 13 forskjellige Facebook-ikoner. Alle disse er plassert i ett og samme bilde.

Resten løser man med CSS ved å posisjonere bildet med koordinater slik at bare det aktuelle området av bildet vises. Skal man for eksempel vise «filmrullikonet» må bildet justeres et visst antall piksler vertikalt og horisontalt.

Hvordan man gjør dette i praksis kan variere, alt etter hvilken bruk man trenger det til og hva slags markup man har på sidene.

Praktisk eksempel

Fire bilder, tre knapper

Fire separate bilder

I dette eksempelet skal jeg bruke fire separate bildefiler, alle hentet fra Everaldo Coelhos ikonsett Crystal Project. Hvert bilde er 24x24 piksler. Og med disse fire bildene skal jeg lage tre forskjellige «knapper» med CSS-sprites:

  • En Ok-knapp
  • En Cancel-knapp
  • En WiFi-knapp som endrer seg ved mouseover

Fra fire til ett bilde

Eksempel CSS-sprites

Det første jeg gjør er å sette sammen de fire bildefilene til ett bilde. Hvordan du gjør dette skal jeg ikke legge meg opp i, men det er altså snakk om klipp-og-lim.

Jeg har valgt å plassere de to i bredden og to i høyden. Med fire bilder i størrelsen 24x24 piksler får jeg da ett bilde i størrelsen 48x48 piksler. Bildene plasseres kloss inntil hverandre, det er ikke noe poeng med for mye tomrom.

HTML for de tre knappene

Jeg vil ha de tre knappene plassert under hverandre, og går for følgende HTML:

<div id="spritesEksempel">
 <div class="ok">Ok</div>
 <div class="cancel">Cancel</div>
 <div class="wifi">WiFi</div>
</div>

Her ser jeg helt bort fra grafikken (den kommer senere) og bruker i stedet tekst på hver knapp.

CSS for de tre knappene

Det her magien kommer inn i bildet, og da gjelder det å holde tunga rett i munnen!

<style>
#spritesEksempel div { background-image:url(/img/131202213835_sprites-eksempel.png); width: 24px; height: 24px; border: 1px outset gray; margin: 3px; }
#spritesEksempel .ok { background-position: 0 0; }
#spritesEksempel .cancel { background-position: -24px 0; }
#spritesEksempel .wifi { background-position: 0 -24px; }
#spritesEksempel .wifi:hover { background-position: -24px -24px; }
</style>

Her har jeg gjort følgende med CSS:

  • Hver knapp settes til 24x24 piksler
  • Legger på en grå ramme rundt hver knapp (har ingenting med CSS-sprites å gjøre)
  • Hver knapp får samme bakgrunnsbilde, nemlig det ene bildet som inneholder samtlige motiver
  • Posisjonen for bakgrunnsbildet justeres for hver enkelt knapp med background-position
    • Det første tallet angir horisontal posisjon
    • Det andre tallet angir vertikal posisjon
    • «0 0» betyr altså helt øverst til venstre
    • «-24px 0» betyr helt øverst, men 24 piksler til siden
  • For WiFi-knappen har jeg også lagt til at background-position endres ved hover

Resultatet

Dette var et veldig enkelt eksempel på bruk av CSS-sprites, ment kun for å illustrere prinsippet. Gjør gjerne et søk på nettet etter «css sprites» og finn andre tilnærminger til CSS-sprites, mulighetene og metodene er mange.

Nedenfor er et litt mer omfattende eksempel med hele 1000 ikoner i én bildefil:

Avansert bruk av CSS-sprites

Bonuseffekt

En ting jeg ikke har nevnt er at filstørrelsen for 4 bilder av 24x24 piksler gjerne er større enn filstørrelsen for 1 bilde av 48x48 piksler. Så alt i alt kan det være du sparer den totale diskplassen og båndbredden ved bruk av CSS-sprites.

I eksempelet mitt utgjorde de fire bildefilene (da de var separate bildefiler) 4967 bytes. Satt sammen til én fil utgjør de bare 3145 bytes.

Les også gårsdagens blogginnlegg om komprimerering av PNG-bilder.

Svend Asbjørn Sylling, 3. desember 2013

Bloggen fra Sylling Hardcode