CSS Sprites sind eine bewährte Technik, um die Ladezeit von Web-Frontends deutlich zu verbessern. Wir zeigen, wie man Sprites mit Sass und Compass automatisiert erstellt und besonders bei Änderungen keine Zeit verliert.
Bessere Ladezeiten durch CSS-Sprites
CSS-Sprites (oder genauer “CSS Sprite Maps”) dienen zur Performance-Verbesserung, indem HTTP-Requests auf jeder Seite eingespart werden. Dazu werden oft benutzte Grafiken wie Icons, Logo, Buttons und andere UI-Elemente in einer einzigen Bilddatei gesammelt, die deutlich schneller vom Browser abgerufen werden kann als viele einzelne Bilder.
Der Einsatz von Sprites ist nicht nur praktisch für den Frontend-Entwickler, sondern gerade hinsichtlich einer besseren Frontend-Performance nahezu unverzichtbar. Jedoch scheint es nicht immer leicht, mal eben ein Sprite anzulegen und vor allem aktuell zu halten…
Welche Probleme gibt es mit Sprites?
Der tägliche Umgang mit Sprites erweist sich meist als mühsam. Bei Anpassung von Hand muss man immer auch die zugehörige CSS-Datei updaten, was oft ein hin- und herspringen zwischen Editor und Photoshop/GIMP bedeutet, um die Positionen ermitteln zu können. Es stellt sich dabei die Frage, in welchem Format man die Sprites zur Bearbeitung vorhalten soll: in Form einer PSD mit individuellen Ebenen? Dann muss man natürlich auch die Disziplin an den Tag legen, immer die PSD zu bearbeiten und zu exportieren, anstatt nur die PNG zu verändern. Alle Projektmitglieder sind somit auf Photoshop angewiesen. Dies kann sich schnell als ein Schlagloch auf der Straße des Erfolgs erweisen.
Problem: CSS Sprites im Team bearbeiten
Sobald man an einem größeren Projekt, mit Versionierung, im Team oder gar in verteilten Teams arbeitet, taucht ein weiteres Problem auf: Änderungen an gemeinsam genutzten Sprites müssen abgestimmt werden, da das automatisierte Mergen von Bildern, zumindest unter Subversion, nicht möglich ist. Es beginnt also spätestens beim Merge das große Absprechen oder gar Raten, wer was wann und warum gemacht hat und wessen Änderungen nun eigentlich aktueller ist. Diese Form der Zusammenarbeit ist sehr fehleranfällig – und wehe man beginnt, womöglich auch noch Sprites aus der Mitte der Map zu entfernen oder anzupassen.
Dies erinnert ein wenig an Jenga – mit dem Unterschied, dass wenn der Turm zusammenbricht, nicht nur ein Projektmitglied verloren hat sondern alle.
Problem: Maximale Sprite-Grenzen
Das Ende des Liedes ist ein Sprite, das über die Zeit unerbittlich wächst und dessen Dimensionen in größeren Projekten durchaus an den Rand des technisch Machbaren grenzen. So liegt die maximale Grenze für Sprites unter iOS bei (dekodierten) 3 Megapixeln, für den IE6 (ich weiß… aber trotzdem!) ist die Maximalgröße 4096×4096 Pixel.
Wie vermeidet man diese Fallstricke am besten?
Die Lösung: Ein automatischer CSS-Sprite-Generator mit Sass und Compass
Aufgrund genannter Probleme drängt es sich förmlich auf, den Prozess der Sprite-Generierung zu automatisieren. Weniger Handarbeit, weniger Fehler. Hier hat man zwei prinzipielle Möglichkeiten, je nachdem wie ausgefeilt die Entwicklungsumgebung für das Projekt aufgesetzt ist:
Option A: Sprite-Generator für Build-Systeme wie Maven
Build-Systeme wie Ant oder Maven vereinfachen die Software-Entwicklung in größeren Projekten und werden meist bei Projekten mit Java, C# oder Ruby eingesetzt. Hier gibt es je nach Build-System kostenpflichtige oder Open-Source bzw kostenlose Ansätze, um einen Sprite-Generator zu integrieren. Hier zwei aktuell gängige Ansätze:
- SmartSprites – Sprite-Generator für Maven
- SpriteSmith – Sprite-Generator für den Taskrunner Grunt
Möchte man jedoch als Frontend-Developer auf einer Windows-Maschine mal den einen oder anderen Ansatz evaluieren, so sieht man sich schnell mit größeren Installationspoblemen konfrontiert, da oft Abhängigkeiten zu 3rd-Party-Tools bestehen (Cairo, ImageMagick, bestimmte Python-Versionen, …) die auf Windows nicht unbedingt problemlos sind. Was tun?
Option B: Sprite-Generator mit Sass und Compass
Für die Arbeit auf dem lokalen System kommt Sass und zusätzlich noch Compass ins Spiel. Dieser Ansatz findet zunächst vollständig lokal beim Frontend-Developer statt. Die Voraussetzungen dafür sind:
Compass baut auf Sass auf und bringt u.a. alle notwendigen Tools zur Sprite-Map-Erzeugung mit. Die benöigten Sprachen/Tools sind mit etwas Doku lesen schnell installiert. Jetzt gehts los:
So funktioniert die Sprite-Generierung mit Sass und Compass
- Der Entwickler wirft alle zu einer Sprite-Map gehörenden Sprites in einen Ordner, der wiederum in einer .scss-Datei referenziert wird.
- Beim Kompilieren der .scss-Dateien erstellt Compass aus allen im angegebenen Ordner befindlichen Sprites eine Sprite Map und das zugehörige CSS.
- Die Sprite Map kann dann mittels Setzen von CSS-Klassen im Markup verwendet werden.
Das Ergebnis: Generiertes Sprite + CSS
Da Compass neben dem Sprite auch das CSS generiert, wird viel Zeit gespart (und Nerven geschont). Ein mühsames Nachsehen der Positionen einzelner Sprites oder gar deren Anordnung in der Map ist damit nicht mehr erforderlich. Auch die Zusammenarbeit in Teams ist problemlos möglich, da alle Entwickler die selben CSS-Klassen verwenden können.
.myProject-sprite, .myProject-cameras, .myProject-deals, .myProject-help, .myProject-home, .myProject-logout, .myProject-prefs, .myProject-world {
background: url('../images/myProject-s24990b9cb0.png') no-repeat;
}
.myProject-cameras {
background-position: 0 -96px;
}
.myProject-deals {
background-position: 0 -32px;
}
Einstellungsmöglichkeiten in Compass
Compass bietet hierbei einige Konfigurationsmöglichkeiten. So gibt es verschiedene Layouts für Sprites und es können Abstände zwischen Sprites definiert werden. Sprites können in der Sprite Map frei positioniert oder zusätzlich die Sprite-Dimensionen im CSS deklariert werden.
Diese Konfigurationen können auch individuell für bestimmte Sprites in der Map eingestellt werden. Abschließend kann sogar automatisch ein externes Tool zur Kompression der Map eingesetzt werden (bspw. pngquant), indem im Ruby-Config-File für das aktuelle Compass-Projekt ein paar Zeilen Code hinzugefügt werden. Der Hook für diese zusätzlichen Aktionen ist der Compass-eigene Event „on_sprite_saved“.
Für die Konfiguration der Sprite Maps als auch einzelner Sprites stehen insgesamt 10 Variablen zur Verfügung, darüber hinausgehende Anpassungen lassen sich durch Funktionen oder Mixins abbilden. Für die meisten Projekte dürften die als Bordmittel verfügbaren Konfigurationsmöglichkeiten allerdings ausreichen.
Styles für Pseudoselektoren
Compass kann außerdem automatisch Styles für Pseudoselektoren erstellen, z.B. für die :hover-Klasse eines Tags. Hierfür ist lediglich das entsprechende Sprite passend zu benennen:
Das zu „folder-icon.png“ passende Hover-Sprite heisst dann einfach „folder-icon_hover.png“; und schon bastelt Compass ohne weiteres Zutun die entsprechenden Styles.
Oft werden für das Einfügen von Zierelementen die Pseudoklassen :before und :after genutzt. In der von Sass erzeugten Struktur ist nicht auf den ersten Blick ersichtlich, wie die Sprite-Styles auf in einem solchen Fall angewandt werden können. Durch die @extend-Funktion ist aber auch das problemlos möglich:
@import "myProject/*.png"; // alle Sprites im Ordner in die Sprite-Map sammeln
@include all-myProject-sprites; // CSS-Selektoren erzeugen
.myElement:before {
@extend .myProject-beforeSprite;
…
}
.myElement:after {
@extend .myProject-afterSprite;
…
}
Die Pseudoklassen lassen sich also unkompliziert bei der Sprite-Map-Generierung berücksichtigen und auch ggf. nur einzelne Sprites eines Ordners in die Sprite Map einbinden.
Fazit
Sass und Compass gehören zunehmend zum Standardwerkzeug in der Web-Entwicklung. Compass stellt dabei ein unkompliziertes und leistungsfähiges Werkzeug als CSS-Sprite-Generator zur Verfügung.