IPC 2014

CSS Sprites – Einsparung an HTTP-Requests durch Kombination von Hintergrund-Bildern

Wie sich ja gewünscht wurde, möchte ich von nun an auch etwas mehr über die Performance von Client-Systemen in Bezug auf Webanwendungen schreiben. Genauer: Wie müssen Webseiten ausgeliefert werden, damit Sie möglichst schnell im Browser des Besuchers dargestellt werden können?
In diesem Beitrag soll es dabei um die CSS Sprites bzw. Image Sprites gehen. Die Yahoo-Präsentation hat ja bereits darauf hingewiesen und hier soll nun erklärt werden, wie es funktioniert.

Problemstellung
Ein Problem, weshalb Seiten oft lange Ladezeiten haben, ist, dass recht viele HTTP-Requests gemacht werden müssen. Da HTTP ein zustandsloses Protokoll ist, muss für jedes Bild, jede JS-Datei und allgemain jede externe Ressource eine neue HTTP-Verbindung zwischen Browser und Server eröffnet werden. Das wäre ja noch nicht problematisch (lediglich umständlich). Das Problem ist aber, dass je nach Browser nur eine bestimmte Anzahl an parallelen HTTP-Requests ausgeführt werden können (oft 2-4). Im Firefox kann diese Einstellung über network.http.max-persistent-connections-per-server auf der about:config-Seite verändert werden.
Dadurch entsteht ein Treppen-Diagramm, das die Gesamtladezeit verdeutlicht: Treppeneffekt beim Laden mehrerer externer Ressourcen
Es wird deutlich, dass einige Beschleunigung des Ladens erreicht werden kann, wenn entweder die Anzahl paralleler Requests erhöht wird oder die Anzahl an Requests verringert wird. Ersteres kann beispielsweise durch unterschiedliche Subdomains gemacht werden (eine für Bilder, eine für JS usw.). Genaueres dazu findet sich beim Beitrag, wenn man auf den Link des Diagramms klickt.
Wir wollen uns jetzt aber mal mit dem anderen Punkt beschäftigen: der Verringerung der HTTP-Requests.

HTTP-Requests verringern könnte man auf 2 Arten: Mehrere Komponenten innerhalb einer Datei konsolidieren (ich hasse dieses Wort, seitdem es in jeder IT-Zeitung steht) oder die Komponenten inline in das HTML-Dokument einbinden. Letzteres geht beispielsweise gut bei CSS (wird z.B. auf Yahoo gemacht) aber auch bei Bildern (aber dann wird der Quellcode richtig hässlich).
Hier soll es um die Konsolidierung mehrerer Komponenten gehen, genauer um das Verringern von Anfragen für Hintergrundbilder.

Jedes mit CSS über url() referenzierte Hintergrundbild benötigt natürlich auch einen HTTP-Request. Aber habt ihr euch mal alte Spiele angesehen (bei aktuellen weiß ichs nicht, dafür hab ich leider kaum noch Zeit)? Dort sind meistens verschiedene GUI-Elemente in einer einzigen Bilddatei zusammengefügt. Hinterher schneidet sich dann das Programm den gewünschten Teil raus. Das spart Speicherplatz und Ladezeit.

Übertragen auf die Webentwicklung ist es ganz ähnlich: Mehrere Hintergrund-Bilder können in eine Grafik-Datei gepackt werden und später trotzdem an der richtigen Position angezeigt werden.
Der erste Schritt dafür ist das Zusammenpacken in eine Datei. Das geht ganz gut mit einem CSS-Sprite-Generator. Dabei sollte allerdings dringend darauf geachtet werden, dass man entweder nur Bilder nimmt, die später horizontal wiederholt werden (repeat-x) oder nur Bilder, die vertikal wiederholt werden (repeat-y) (bei mir traf ersteres dazu, deshalb kann ich die Tauglichkeit des verlinkten Generators für Letzteres nicht einschätzen). Zu den Gründen unten mehr.
Jedenfalls spuckt der Generator letztlich eine Bilddatei aus, in der alle eure Hintergründe enthalten sind. Dazu gibts noch einen CSS-Code.

Allein mit den Anweisungen dort beim Generator habe ich es allerdings nicht hinbekommen, die Sprites zum Laufen zu bekommen, sondern mir war noch dieser Beitrag behilflich. Zuerst muss die Sprite-Grafikdatei nämlich einmal eingebunden werden. Und zwar am besten für alle CSS Regeln, bei denen eines der im Sprite enthaltenen Bilder als Hintergrundbild genutzt wird. (Beispiel siehe unten)

Anschließend kann man sich um das Ersetzen der alten Hintergrundregeln kümmern, denn die werden nun nicht mehr benötigt. Je nachdem, welche CSS-Regeln obiger Generator ausspuckt, ersetzt ihr background-image nun nur noch durch background-position (also inklusive den vom Generator ausgepuckten Werten). Dadurch wird das Sprite an die für das bestimmte Element korrekte Position verschoben.

Nun aber zum repeat. Wenn ihr bisher die Multiformat-Eigenschaft background benutzt habt, müsst ihr das jetzt aufdröseln, denn es wird ja nur noch background-position und background-repeat benötigt. Jedenfalls werdet ihr eventuell schnell merken, dass wenn ihr repeat-x verwendet, es kein hübsches Hintergrundbild wie früher gibt. Der Grund dafür sind unterschiedlich breite Hintergrundbilder. Dadurch entstehen mitunter neben dem Bild weiße (oder transparente; je nachdem, was man einstellt) Ränder. Für ein repeat-x werden aber durchgängige Bilder benötigt.
Deshalb gibt es 2 Wege dieses Problem zu beheben: Entweder alle Bilder nachträglich auf gleiche Breite ziehen. Oder (von mir präferiert) einfach nur den ersten Pixel in der Breite des Sprite-Bildes verwenden (bzw. gleich nur 1px breite Bilder dem Sprite-Generator geben). Kann man ganz einfach per Irfan View oder auch irgendeinem anderen Grafikprogramm auswählen, freistellen / kopieren und entsprechend abspeichern. Es ist sowieso nur ein 1px breites Bild erforderlich, da der Rest ja per repeat-x generiert wird.

Und jetzt kommt noch das zweite Problem, auf das ich gestoßen bin: Ich habe einen Seiten-Hintergrund, der 500px hoch ist (Verlauf). Wenn die Seite länger ist, wird einfach die angegebene Hintergrundfarbe angezeigt. Wenn nun aber unterhalb dieses Bildes im Sprite noch ein völlig anderer Hintergrund kommt, weiß CSS natürlich nicht, wo es das Bild beenden soll (insbesondere da man per CSS zwar das Hintergrundbild verschieben nicht aber einen bestimmten Bereich ausschneiden kann). Entsprechend wird dann einfach der darunterliegende Hintergrund noch mit angezeigt. Entweder man wählt zur Behebung dieses Problems sehr große vertikale Abstände zwischen den einzelnen Hintergründen (diese Lösung ist allerdings nicht sehr flexibel, denn eventuell wird in der Zukunft eine noch längere Seite erstellt, wo der Abstand dann nicht mehr ausreicht) oder man wählt für das Sprite nur Hintergrundbilder von Elementen, deren Höhe feststeht (per CSS-Attribut height; teilweise auch bei Inline-Elementen, jedoch muss da eventuell auf die Schriftgröße geachtet werden – ist diese nämlich relativ angegeben, ist auch die Höhe des Elements variabel).

Nun noch ein kleines Beispiel zur Verdeutlichung:
Alte Regeln:

#header {background: url(bild1.jpg) top left repeat-x; height:80px;}
ul.menu li {background: url(bild2.jpg) top left repeat-x; height:15px;}

bild1.jpg und bild2.jpg sind jeweils 1px breit. Durch den Sprite-Generator jagen, Sprite-Datei runterladen bzw. auf Webserver hochladen.

Sprite-Bild einmalig einbinden für alle Elemente, die einen im Sprite enthaltenen Hintergrund haben:

#header, ul.menu li {background-image:url(bg_sprite.png);}

Mit Hilfe der im Generator angegebenen Regeln die alten Regeln ersetzen:
Generator spuckt zum Beispiel aus:

.sprite-bild1 { background-position: 0 -30px; } 
.sprite-bild2 { background-position: 0 -110px; }

Einbau in vorhandenes CSS:

#header {background-position: 0 -30px; background-repeat: repeat-x;}
ul.menu li {background-position: 0 -110px; background-repeat: repeat-x;}

Und das wars. Mit 2 Bildern macht das noch nicht so viel Sinn, aber ich denke das reicht zum Verdeutlichen.

Falls ihr noch Fragen habt zu diesem Thema, freue ich mich über Kommentare. Euren Erfolg durch diese Maßnahme prüfen könnt ihr übrigens mit Firebug (Tab Net) sowie YSlow (Tab Performance).


Schlagwörter: , ,

36 Kommentare bisher »

  1. pla sagt

    am 3. April 2008 @ 08:31

    Schicker Artikel, hast dir wirklich Mühe gegeben!

  2. Wortopia.de - Die deutsche Wortspielpage - BETA sagt

    am 8. April 2008 @ 20:45

    […] so ist der Server trotzdem ordentlich am werkeln. Ein paar Performance-Schrauben hab ich schon gedreht, aber wenn die Besucherzahlen so bleiben, muss etwas Solides her… Mal sehen, was die Tage […]

  3. SeeeD sagt

    am 17. April 2008 @ 14:56

    Toller Artikel..
    Gerade die Stelle wie man die http-Requests erhöhen kann fand ich super.
    Werde ich direkt ausprobieren und schauen ob das Laden schneller und flüssiger abläuft :)

  4. Mira sagt

    am 18. April 2008 @ 13:31

    Wow du hast dir echt viele Gedanken zum Thema gemacht. Gerade von der Idee, Bilder und JS auf verschiedene Domains auszulagern bin ich recht begeistet. Auch heutzutage haben nur ca 50% alle User DSL, da ist die Ladezeit-Optimierung durchaus relevant.

  5. devtimes » HTTP-Requests mit Sprites oder Inline-Grafiken einsparen sagt

    am 23. April 2008 @ 12:15

    […] phpperformance.de wird ein Verfahren beschrieben, mit dem sich Hintergrundbilder so verändern lassen, dass sie alle […]

  6. Performancegewinn durch virtuelles JavaScript-File » Beitrag » PHP Performance sagt

    am 15. Juli 2008 @ 16:17

    […] alleine die Startseite über 20 verschiedene JS-Files lädt (davon bekanntlich immer nur zwei gleichzeitig), begann ich dort zu schauen was sich machen lässt. Eine Verringerung der Anzahl JS-Files […]

  7. Performance-Optimierung für den Blog | Onkel Andys Tagebuch sagt

    am 18. Juli 2008 @ 13:17

    […] HTTP-Requests minimieren Der große Vorteil des weiter unten nochmals beschriebenen PHP Speedy -Plugins ist die Minimierung der http-Requests, da sowohl js-Files als auch css-Dateien in je eine Datei zusammen gefasst werden! Das kann also schon mal einen netten Performance-Boost bringen. Neben den vielen verschiedenen css- und js-Dateien durch den Einsatz mehrerer Plugins stellen auch mittels css eingebundene Bilddateien ein Problem dar. Nutzt man wie ich beispielsweise CSS, um nette Icons zu Links hinzuzufügen, erhöht sich die Zahl der http-Requests rapide. Einen Geschwindigkeitsgewinn kann man durch das Nutzen von so genannten Sprites erzielen. Auf phpperformance.de gibt es ausführliche Informationen zum Einsatz von diesen CSS-Sprites. […]

  8. tanila sagt

    am 23. August 2008 @ 19:16

    Hallo,

    habe einen CSS Sprite Generator geschrieben in PHP (CLI)

    Er kann die background-images automatisch ersetzen.

    Wenn Ihr interessiert seid:
    http://tanila.de/smartsprite/index.php

    Grüsse
    tanila

  9. tecM0 sagt

    am 30. Oktober 2008 @ 12:12

  10. test sagt

    am 4. Dezember 2008 @ 16:44

    hallo

    gibt es ein tool, mit dem man sich die anzahl der HTTP-Requests einer webseite anzeigen lassen kann?

  11. Jan sagt

    am 4. Dezember 2008 @ 16:59

    Mit YSlow geht das. Du brauchst dafür:
    1. Firefox
    2. Firebug (Plugin für Firefox)
    3. YSlow (Plugin für Firebug)

  12. tanila sagt

    am 4. Dezember 2008 @ 17:01

    Hallo test,

    komischer name, den du da hast ;)

    HTTP-Requests kann zb. YSlow fuer Firebug anzeigen.
    YSlow ist eine Erweiterung fuer Firebug.

    http://developer.yahoo.com/yslow/

    Gruesse
    tanila

  13. Einige Links » Beitrag » PHP Performance sagt

    am 1. Februar 2009 @ 18:06

    […] nennt sich treffend Website Optimization. Zuerst ein Beitrag zu CSS Sprites, mit denen ich mich ja auch schon beschäftigt habe. Außerdem ein weiterer Weg mehrere CSS-Dateien automatisch zusammen zu fassen, obwohl ich […]

  14. CSS Sprites - Background Repeat Problem | Webdesignblog sagt

    am 31. März 2009 @ 10:29

    […] des a-Tags von HTML realisieren, man benötigt keinen Preloader für den Hover-Bildaustausch, und man spart sich ein paar HTTP-Requests, da weniger Einzel-Daten geladen werden müssen. Doch ein Problem konnte ich bislang damit nicht […]

  15. CSS-Sprites Quellensammlung sagt

    am 14. April 2009 @ 08:16

    […] CSS Sprites Einsparung an HTTP-Requests durch Kombination von Hintergrund-Bildern (.de) […]

  16. CSS-Sprites Quellensammlung / Design, Webdesign / Seraph Design Solutions // Webdesign, Printdesign, Leveldesign // Portfolio von Benjamin Schulz sagt

    am 18. April 2009 @ 19:17

    […] CSS Sprites Einsparung an HTTP-Requests durch Kombination von Hintergrund-Bildern (.de) […]

  17. Sprites mit CSS | Guru 2.0 sagt

    am 19. April 2009 @ 12:36

    […] phpPerformance: css-Sprites […]

  18. CSS Sprites : Hand-drauf Ich und mein Studium sagt

    am 24. April 2009 @ 20:17

    […] das genau funktioniert wird bei phpperfomance.de und bei webkrauts.de […]

  19. WordPress-Websites beschleunigen 2: Grafiken Optimieren » Peruns Weblog sagt

    am 14. Mai 2009 @ 16:08

    […] auch HTTP-Anfragen minimieren, was zusätzlich zur Optimierung der Website beiträgt. Hier ein interessanter Artikel […]

  20. gr4ys blog - Tabellenquälerei. sagt

    am 3. Juli 2009 @ 13:03

    […] CSS Sprites – Einsparung an HTTP-Requests durch Kombination von Hintergrund-Bildern […]

  21. Grafische Datumsanzeige für WordPress | Roman Harcke sagt

    am 31. Juli 2009 @ 11:39

    […] CSS Sprites – Kombination von Hintergrundbildern […]

  22. Web Based Programming » Web programming tutorials sagt

    am 13. Oktober 2009 @ 13:36

    […] CSS Sprites – reduce HTTP Requests to speed up web page (dt.) […]

  23. Robert sagt

    am 20. Dezember 2009 @ 15:31

    Da ich auch meine HTTP Request verringern möchte, bin ich auf Deinen Artikel getstoßen. Sehr gut beschrieben, da werde ich mich mal an die Arbeit machen….

  24. Matthias sagt

    am 21. Dezember 2009 @ 13:18

    Schön beschrieben. Wenn man viel Traffic auf der seite hat sollte man einiges davon beachten.

  25. Xian sagt

    am 18. Januar 2010 @ 16:05

    Wenn man mehrere Buttons mit gleicher oder ähnlicher Breite hat, ist diese Idee sicherlich sinnvoll. So habe ich alle 3 Zustände meiner Buttons (normal, hover, aktiv) in je eine einzelne Grafik gebracht.

    Für 1 px breite und x px hohe Hintergrundbilder oder Bilder mit stark abweichenden Maßen finde ich diese Technik aber eher ungeeignet; eben aus den von dir beschriebenen Problemen.

  26. Wie wird man 2010 SEO-Superstar? >> Headline, SEO sagt

    am 20. Januar 2010 @ 08:03

    […] zu den Standard-Maßnahmen zur Ladezeit-Optimierung gibts hier.  Auch nicht schlecht: Sprites für Icons auf einer Seite verwenden. Wer seinen PageSpeed mal eben testen will, nutzt das […]

  27. Paul sagt

    am 6. Februar 2010 @ 14:02

    das Thema an sich ist ja nicht mehr so taufrisch, aber die Darstellung des Sachverhaltes doch sehr umfassend.
    Danke auch für den Tipp mit dem Online-Tool.
    Auch ganz nett ist dieses hier:
    http://css-sprit.es/

  28. Mick sagt

    am 10. Februar 2010 @ 20:08

    Spriteme.org ist das einfachste und meiner Meinung nach beste Tool. Am besten danach die Bilder noch durch einen Crusher schicke, so konnte ich die Ladezeit (mit anderen Optimierungen) von 3-4 auf knapp 1 Sekunde drücken, ohne, dass die Seite schlechter aussieht oder sonstwas :)

  29. Michael Finger sagt

    am 15. April 2010 @ 01:57

    Danke für die Erklärung, jetzt habe ich es wenigstens verstanden und kann es auf meiner Webseite umsetzen. Mal schauen mit welchen der Programme ich am besten umgehen kann.

  30. Tutorial: Geschwindigkeit und Ladezeit von Webseiten optimieren » Webseite, Plugin, Tipp, Bilder, Plugins, Cache » IhrWebprofi.at sagt

    am 2. November 2010 @ 22:34

    […] vieler kleiner Bilder falls möglich CSS Sprites verwenden, um die Anzahl der HTTP-Requests weiter zu reduzieren. Tipp: leicht zu bedienende CSS […]

  31. Sebastian sagt

    am 4. November 2010 @ 13:10

    Mmmh, ist zwar gut beschrieben, aber einsetzen tust du es hier auf deinem Blog nicht, oder?

  32. Smartphone Test sagt

    am 11. Juni 2011 @ 09:04

    Ich habe mich jetzt etwas intensiver damit beschäftigt und muss echt sagen, klasse Sache.

  33. Handytarifevergleich 24 sagt

    am 18. April 2012 @ 21:39

    Hallo,

    ich habe mir vorhin mal CSS Sprites gebaut und die Ladezeit ist meines Empfinden nach etwas schneller geworden. Google hat ja ein Site Speed-Tool und wenn ich ohne Sprites die Seite bei dem Tool teste, lädt meine Website 0,3 Sek. schneller als mit Sprites. Habe das 3x getestet.

    Woran liegt das? Soll ich sie trotzdem verwenden?

  34. GhostGambler sagt

    am 19. April 2012 @ 09:18

    Vermutlich egal, weil dein Anwendungsfall zu klein ist.
    Das ist zum Beispiel eher bei addThis wichtig, dort gibt's viele kleine Bilder, und wenn man da für jedes einzeln einen Request absetzen müsste, wäre der Browser eine Weile beschäftigt. Beispiel: https://s7.addthis.com/static/r07/widget044.png

  35. Wordpress Tuning sagt

    am 25. Juli 2013 @ 18:32

    […] CSS Sprites – Einsparung an HTTP-Requests durch Kombination von Hintergrund-Bildern […]

  36. SpriteMe lokal installieren und CSS-Sprites erstellen | Keleo sagt

    am 3. September 2014 @ 21:07

    […] und warum man diese nutzen sollte. Wer nicht weiß worum es dabei geht, der sollte sich einfach einen der verlinkten Artikel vornehmen, dort wird die Technik vorgestellt und […]

Komentar RSS · TrackBack URI

Hinterlasse einen Kommentar

Name: (erforderlich)

eMail: (erforderlich)

Website:

Kommentar: