CSS Sprite - Ladegeschwindigkeit optimieren und HTTP-Requests verringern
-
CSS
- 26 Mai, 2010
- Kommentare (12)
CSS Sprite bedeutet in der englischen Sprache Kobold oder Geistwesen und ist der Begriff für eine Grafik, die aus mehreren einzelnen Grafiken zu einer einzigen Grafik zusammengefügt wird. Diese Technik ist nicht neu, denn sie wurde bereits früher beim Erstellen von Computerspielen verwenden, da Grafikspeicher damals noch klein waren und das Nachladen lange dauerte. Auch im Webdesign sind CSS Sprites keine "brandneue" Technik, sondern wurde bereits im Jahr 2004 von Dave Shea bei A List Apart vorgestellt. Allerdings erst in den letzten Jahren fand man mehr und mehr Websites, die diese Technik nicht zuletzt auch aufgrund der daraus resultierenden verbesserten Ladezeit anwenden. Denn der größte Vorteil von CSS Sprites liegt in der Einsparung von HTTP-Requests, der Reduzierung der Gesamtgröße der Bilder und somit in der Verkürzung der Ladezeit von Webseiten.
Dass die Ladezeit mittlerweile als Kriterium bei Suchmaschinenpositionen immer mehr Gewichtung bekommt, dürfe sich bereits herum gesprochen haben. Und die Suchmaschinenbetreiber gehen mit gutem Beispiel voran, aber nicht nur Google oder Yahoo sondern auch andere große Webseiten wie Amazon oder Mozilla verwenden CSS Sprites. Der "Trick" bei dieser Herangehensweise ist, anstatt viele kleine Einzelgrafiken zu laden, wird eine größere Grafik mit allen Einzelgrafiken erstellt. Diese Sprite Grafik wird dann per CSS mit der Eigenschaft "background-position" an den Anzeigenbereich verschoben, so dass das entsprechende Element wie im folgenden CSS Tutorial sichtbar wird.
HTML - Anlegen der Ländernavigation
Da die Bereitstellung einer Länderauswahl nichts anderes als eine simple Auflistung der zu verwendenden Länder darstellt, wird das Ländermenü wie folgt mittels einer unsortierten Liste strukturiert.
Code-Beispiel
...
<ul class="flagmenu">
<li><a href="#" id="de" class="flags">Deutschland</a></li>
<li><a href="#" id="ch" class="flags">Schweiz</a></li>
<li><a href="#" id="cz" class="flags">Tschechien</a></li>
<li><a href="#" id="es" class="flags">Spanien</a></li>
<li><a href="#" id="fr" class="flags">Frankreich</a></li>
<li><a href="#" id="gb" class="flags">Groß Britanien</a></li>
<li><a href="#" id="it" class="flags">Italien</a></li>
<li><a href="#" id="us" class="flags">USA</a></li>
<li><a href="#" id="za" class="flags">Süd Afrika</a></li>
</ul>
...
CSS Sprite - Die umständliche Variante mit vielen Grafiken
Bisher wurde jedem Link per CSS über den ID-Selektor eine entsprechende Hintergrund-Grafik zugewiesen. Bei der Umsetzung dieser Länderauswahl ohne CSS Sprite würden somit neun (!) HTTP-Requests zur Übermittlung der Länderflaggen von Nöten sein.
CSS Code
#ch {background: transparent url(ch.png) no-repeat 0 50%}
#cz {background: transparent url(cz.png) no-repeat 0 50%}
#de {background: transparent url(de.png) no-repeat 0 50%}
#es {background: transparent url(es.png) no-repeat 0 50%}
#fr {background: transparent url(fr.png) no-repeat 0 50%}
#gb {background: transparent url(gb.png) no-repeat 0 50%}
#it {background: transparent url(it.png) no-repeat 0 50%}
#us {background: transparent url(us.png) no-repeat 0 50%}
#za {background: transparent url(za.png) no-repeat 0 50%}
.flagmenu {
font-size: 13px;
list-style-type: none;
margin:0;
padding:0;
}
.flags {
color: #fff;
display:block;
line-height: 1.4;
padding: 0 0 0 24px;
text-decoration: none;
}
Das Ergebnis des Einsatzes dieser CSS Sprite sieht dann wie in der Abbildung gut zu erkennen ist, folgendermaßen aus: Länderauswahl ohne CSS Sprite. Der Browser muss allein für die Bilder 9 HTTP-Requests durchführen und für die 9 Flaggen insgesamt 7,13Kb laden.
![]()
CSS ohne Einsatz einer Sprite Grafik - 9 HTTP-Requests, 7,13Kb
Wie erstellt man Sprite-Grafiken?
Wie nach Rom, gibt es auch in diesem Fall mehrere Wege, die zum Ziel führen. Beispielsweise könnte man die Flaggen wie in der kleinen Abbildung hier, dicht aneinander packen. Allerdings wären hierfür Änderungen am HTML-Markup nötig. Deshalb werden im folgenden Beispiel alle Flaggen mit einem Abstand von 50px untereinander in der Sprite-Grafik ausgerichtet. So wird pro Linkzeile nur eine Fahne angezeigt und kein anderes Bildteil ragt aus Versehen in einen anderen Link hinein. Ein guter Tipp ist es, die grafischen Elemente die links von der Schrift angezeigt werden sollen, rechts im Sprite-Image anzulegen. Dies kann man mit einem Grafikprogramm wie Photoshop machen oder man nutzt einen Webservice wie den CSS Sprite Generator.
![]()
CSS Sprite Generator mit CSS Ausgabeoptionen
Man muss lediglich alle Flaggen die man braucht in eine ZIP-Datei packen und hochladen. Dort kann man auch den Abstand zwischen den einzelnen Bildern bestimmen und der Sprite-Generator erstellt die Sprite-Grafik, inklusive dem dazugehörigen CSS.
CSS - Die CSS Sprite Variante mit einer Grafik
Für die Herangehensweise mit Sprite-Grafik wird für die allgemeine Klasse .flags die erstellte Grafik "flag-sprite.png" zugewiesen (siehe Zeile 2). Der restliche CSS-Code bleibt unverändert.
CSS Code
.flags {
background: transparent url(flag-sprite.png) no-repeat;
color: #fff;
display:block;
line-height: 1.4;
padding: 0 0 0 24px;
text-decoration: none;
}
...
Aufgrund der Verwendung der Sprite-Grafik muss nun nur noch für den jeweiligen Link die Position des Hintergrundbildes verschoben werden. Damit nur ein bestimmter Bereich der Grafik wie in der folgenden Demonstration angezeigt wird, wird die Hintergrund-Position um den jeweiligen Wert nach unten verschoben.
CSS Code
...
#ch {background-position: 0 4px;}
#cz {background-position: 0 -57px;}
#de {background-position: 0 -118px;}
#es {background-position: 0 -180px;}
#fr {background-position: 0 -241px;}
#gb {background-position: 0 -301px;}
#it {background-position: 0 -362px;}
#us {background-position: 0 -423px;}
#za {background-position: 0 -485px;}
Wichtig ist, dass ihr wie im CSS-Code gut zu erkennen ist, das "Minus" nicht vergesst, da ansonsten die ID mit dem Länderkürzel "ins Leere greifen" würde und ihr somit keine Flagge angezeigt bekommen würdet.
![]()
CSS mit Einsatz einer Sprite Grafik - 1 HTTP-Requests, 3,05Kb
Dies resultiert in nur einem HTTP-Request und einer Bildgröße von nur 3,05Kb! Na gut, ein wenig mehr als die Hälfte Kilobyte eingespart, ist jetzt aber auch nicht so viel. Allerdings enthält die "flag-sprite.png" Bilddatei auch alle inaktiven Status-Bilder der Flaggen. Hier wäre also die Ausgangslage 18 HTTP-Requests (!) und ca. 14Kb Bildmaterial zu laden. Das würde einer Einsparung von 80% des Bildmaterials entsprechen. Je nach Umfang der zu verwendenden Bildelemente kann bei einer solchen Umsetzung eine durchaus signifikante Einsparung erreicht werden.
Länderauswahl mit aktiven Menüpunkt
Da zu einer guten verständlichen Benutzerführung innerhalb eines Menüs auch das Hervorheben des jeweils ausgewählten Landes gehören würde, wird im letzten Schritt der HTML-Code um die #active ergänzt, um diesen Menüpunkt dann via CSS mit der "aktiven Grafik" ausstatten zu können. Die Verlinkung beim Menüpunkt "Frankreich" fällt weg, da der Menüpunkt aktiv ist und eine Verlinkung somit keinen Sinn ergibt.
Code-Beispiel
...
<ul class="flagmenu">
<li><a href="#" id="de" class="flags">Deutschland</a></li>
<li><a href="#" id="ch" class="flags">Schweiz</a></li>
<li><a href="#" id="cz" class="flags">Tschechien</a></li>
<li><a href="#" id="es" class="flags">Spanien</a></li>
<li class="active">
<strong id="fr" class="flags">Frankreich>Frankreich</strong>
</li>
<li><a href="#" id="gb" class="flags">Groß Britanien</a></li>
<li><a href="#" id="it" class="flags">Italien</a></li>
<li><a href="#" id="us" class="flags">USA</a></li>
<li><a href="#" id="za" class="flags">Süd Afrika</a></li>
</ul>
Herausstechendens Merkmal des CSS-Codes an dieser Stelle ist, dass beim Überfahren der jeweiligen Menüpunkte mit der Maus die Positionierung der Sprite-Grafik eine zusätzliche Ausrichtung erhält, denn schließlich soll die "inaktive Flagge" die sich weiter unten in der Sprite-Grafik befindet durch die "aktive Flagge" ersetzt werden.
CSS Code
.flagmenu {
list-style-type: none; font-size: 13px; margin: 0; padding: 0;}
.flags {
background: transparent url(flag-sprite.png) no-repeat;
color: #fff;
display:block;
line-height: 1.4;
padding: 0 0 0 24px;
text-decoration: none;
}
a.flags:hover {
text-decoration:underline;
}
#ch {background-position: 0 -547px;}
#cz {background-position: 0 -608px;}
#de {background-position: 0 -669px;}
#es {background-position: 0 -731px;}
#fr {background-position: 0 -792px;}
#gb {background-position: 0 -852px;}
#it {background-position: 0 -913px;}
#us {background-position: 0 -974px;}
#za {background-position: 0 -1036px;}
.active #ch, #ch:hover, #ch:focus {background-position: 0 4px;}
.active #cz, #cz:hover, #cz:focus {background-position: 0 -57px;}
.active #de, #de:hover, #de:focus {background-position: 0 -118px;}
.active #es, #es:hover, #es:focus {background-position: 0 -180px;}
.active #fr, #fr:hover, #fr:focus {background-position: 0 -241px;}
.active #gb, #gb:hover, #gb:focus {background-position: 0 -301px;}
.active #it, #it:hover, #it:focus {background-position: 0 -362px;}
.active #us, #us:hover, #us:focus {background-position: 0 -423px;}
.active #za, #za:hover, #za:focus {background-position: 0 -485px;}
CSS Sprites - Fazit:
Durch eine CSS Sprite ergibt sich bei vielen Websites ein großes Einsparungspotenzial. Einige Websites können durchaus 30-50% bei der Ladezeit einsparen. Nicht zu verkennen ist aber auch die Wartbarkeit solcher (Bild-)Dateien. Das einfache Austauschen einer einzelnen Grafik im Sprite kann durchaus länger dauern, insbesondere dann wenn sich deren Ausmaße ändern sollten. Auch die "Positionsfindung" mit CSS muss eingeübt werden. Nichtsdestotrotz überwiegt das enorme Einsparungspotenzial der Ladezeit.
Informationen über den Gastautoren
Verfasst hat diesen Artikel zum Thema CSS-Sprites Sven Wolfermann. Er ist freier Webentwickler mit Schwerpunkt Frontendentwicklung HTML und CSS. Zudem ist Sven zertifizierter TYPO3 Integrator und schreibt für das TYPO3 Magazin TY-MA. Er beschäftigt sich seit ca. 2 Jahren intensiv mit dem Thema Frontend Performance und führt zu diesem Thema seit kurzem auch einen Tumblr-Blog: maddesigns.tumblr oder twittert darüber. In seiner Freizeit entspannt sich der 32-jährige im Garten und tobt mit seiner 2-jährigen Tochter.
Werde auch du Gastautor im Webstandardblog!
Um Themengebiete wie diese, für die sich die Leser interessieren anbieten zu können, möchten wir über diesem Wege weiterhin anderen Bloggern die Möglichkeit geben, ihr Fachwissen mit unseren Lesern teilen zu können. Voraussetzung ist lediglich, dass sich diese Artikel in den vorhanden Kategorien unseres Blogs untergebracht werden können und der jeweilige Autor über entsprechendes Fachwissen verfügt.

















Danke, für ein wiedermal klasse Tutorial.
Auch wenn mir der Umgang mit CSS Sprites bereits bekannt ist, aber das es so einfach wie mit dem Sprite-Generator geht hätte ich nicht gedacht. So hätte ich mir früher einiges an Zeit ersparen können ;o)
27 Mai 2010, 09:19
Es freut mich, dass mein Artikel veröffentlicht wurde. Danke Heiko!
27 Mai 2010, 09:26
@Sven: Ist doch selbstverständlich, warum auch nicht und ich hab' zu danken!
27 Mai 2010, 10:02
gerade bei css-sprites wünsche ich mir oft, alle browser würden background-position-x und background-position-y unterstützen. mal angenommen, die flaggen sind untereinander angeordnet und links neben jeder farbigen flagge ist das schwarz-weiße pendant.
dann würde man - wie hier gezeigt - für jedes element seperat die s/w-flagge zuweisen. für den hover-zustand müsste man dann allerdings nicht noch einmal den rattenschwanz an css-anweisungen abtippen, sondern könnte einfach:
.flags:hover { background-position-x: -30px }
schreiben. je nach breite der flaggen.
das wiederum erinnert mich daran, dass ich mal eine petition pro background-position-x/-y, adressiert an alle browser-hersteller, die es nicht unterstützen, aufsetzen wollte :-)
27 Mai 2010, 14:16
sehr gutes tutorial :)
die technik ist aber schon etwas älter ;)
sehr gut für grafik-menus mit 3 unterschiedlichen zuständen
auch google nützt diese technik schon lange.
hier ein bild:
http://www.google.de/images/srpr/nav_logo13.png
27 Mai 2010, 14:33
@Emanuel: Der Petition schließe ich mich gern an ;o)
@Markus: Freut mich, wenn dir das Tutorial gefällt. Aber das die Technik nicht neu ist wurde oben ja bereits erwähnt, auch das Google ( und viele andere Global-Player ) CSS-Sprites schon ein weile nutzt.
27 Mai 2010, 14:37
Bei allen Vorteilen sollte man die Nachteile bzw. Fallstricke aber nicht vergessen.
Ein schönes Beispiel sind bspw. Alphatransparenzen in Sprites, die Speicher ohne Ende fressen.
Zum Thema: http://blog.vlad1.com/2009/06/22/to-sprite-or-not-to-sprite/
27 Mai 2010, 16:23
Interessanter Artikel. Muss ich gleich mal ausprobieren.
Wobei ich noch nicht wirklich überzeugt bin, ob das soviel bringt, zumindest nicht bei einer geringen Anzahl von Bildern.
BTW: Wieso wurde meine erste E-Mail-Adresse als ungültig abgelehnt? Ist eine gültige Rocketmail.com-Adresse...
27 Mai 2010, 16:37
@mike: Bezüglich der Nachteile gebe ich dir natürlich recht, wobei die in dem Artikel beschriebene Sprite-Grafik mit 15.000px auch "ein wenig groß" geworden ist ;o)
@Joern: Bei einer geringen Anzahl ist das Einsparpotential natürlich geringer, es geht aber auch um die Requests und das lohnt sich eigentlich immer. Der Fehler bezüglich der Mail, liegt am Backend des Bloganbieters. Deine Mail ist natürlich nicht ungültig ;o) ( ignorieren und Feld frei lassen )
inwieweit klappt das noch bei dynamischen seiten? ich meine, die positionen der sprites sind klar festgelegt. d.h. ein div drum rum ist pflicht, oder?
Ich finde die Idee mit den Sprites seit dem Tag klasse, als ich es das erste Mal bei Amazon im Einsatz gesehen habe.
Den großen Nachteil sehe ich aber darin, dass man es nicht wirklich mit dynamisch skalierbaren Elementen nutzen kann, da die Grafiken meist fixe Werte benötigen.
Beispiel wäre ein Button mit abgerundeten Ecken (fern den CSS3-Möglichkeiten, Hallo IE) so habe ich hier bisher keine sinnvolle Lösung gefunden, mit Sprites arbeiten zu können ohne evtl. mit leeren spans und position:absolute arbeiten zu müssen.
Wenn ich 4 - 5 spans innerhalb des Buttons verschachteln möchte, komme ich um mehrere Grafiken immer nicht drumherum.
Any ideas? Vielen Dank im Voraus.
Danke für die Messzeiten und die Codeschnipsel. Es ist wirklich verwunderlich, wie viele große Seiten oder Online-Shops nach wie vor mehrere Grafiken einzeln implementieren und dadurch wertvolle Ladezeit verschenken.
Viele Grüße aus Winterhude