Vorheriger Artikel Nächster Artikel

CSS-Entwicklung: SASS im Einsatz

Aus dem
t3n Magazin Nr. 27

03/2012 - 05/2012

CSS-Entwicklung: SASS im Einsatz

Vorkompiliertes ist in aller Munde, und immer weniger Frontend-Entwickler verweigern sich dem Thema. Wo man hinschaut, sieht man die gleichen Einleitungen zu dem Thema. Es werden Variablen vorgestellt sowie Vererbung erklärt. Und dann? t3n zeigt praktische Anwendungsfälle.

Welche Türen stehen mit vorkompilierten Stylesheets offen? Wie lassen sich Variablen und Vererbung nützlich in eigene Projekte integrieren? Und womit reizt man SASS aus? Nach der Einführung [1] in die Grundfunktionen von SASS [2] kommen nun also Erweiterungen, Mixins und Compass zum Einsatz.

Erweiterungen

Wie oft kommt es vor, dass verschiedene Elemente auf einer Seite sich zwar ähneln, nicht aber gleichen? Buttons zum Beispiel, oder Hinweisboxen. Letztere sind auch Ausgangspunkt des folgenden Beispiels: Neben allgemeinen Hinweisboxen soll es auch eine Variante für Fehlermeldungen geben.

Separate Fehler- und Erfolgsmeldungen

.message {
 background-color: lighten($main-color, 30%);
 border: 0.1em solid $main-color;
 padding: 1em;
 margin: 1em 0;
   p:last-child {
  margin-bottom: 0;
 }
}
.error {
  @extend .message;
 background-color: lighten($error-color, 30%);
 border-color: $error-color;
}

Der erzeugte CSS-Code erhält nun keine Mehrfach-Deklarationen, sondern erweitert dank dem „@extend“-Element die entsprechenden Selektoren und lagert nur die Ergänzungen aus.

Erzeugter CSS-Code

.message, .error {
 background-color: #42ff62;
 border: 0.1em solid #00a81c;
 padding: 1em;
 margin: 1em 0;
}
.message p:last-child, .error p:last-child {
 margin-bottom: 0;
}
.error {
 background-color: #ff9999;
 border-color: red;
}

Dank SASS lässt sich CSS mit angemessenem Aufwand entwickeln.
Dank SASS lässt sich mit angemessenem Aufwand entwickeln.

Generell lässt sich dies auch im HTML-Code erreichen, indem die Fehlerboxen einfach mit den Klassen „message“ und „error“ ausgezeichnet sind. Das funktioniert in einem so einfachen Beispiel ziemlich ähnlich, in größeren Projekten kann es aber von Vorteil sein, den HTML-Code unberührt zu lassen. Zudem erleichtert die zentralisierte Formatierung im CSS-Code die Wartung.

Erweiterungen mit Mixins erweitern

Mixins sind im Grunde Code-Blöcke, die man in der SASS-Datei an beliebiger Stelle aufruft. Ihr Inhalt wird dann an dieser Stelle in die CSS-Datei geschrieben. Der Clou ist aber die Tatsache, dass ein Mixin, ähnlich einer Funktion in echten Programmiersprachen, mit übergebenen Variablen umgehen kann, die dann in diesem Mixin zur Verfügung stehen.

Mixins definieren

@mixin box-shadow($value) {
 -moz-box-shadow: $value;
 -webkit-box-shadow: $value;
 box-shadow: $value;
}

Dass dieses Mixin Tipparbeit erspart, ist offensichtlich: Die Vendor-Prefixe für eine CSS-Eigenschaft, in diesem Fall den Schatten, sind einmal definert und müssen nicht bei jedem Aufkommen erneut getippt werden. Entsprechend kommt das Mixin fortan in Stylesheets zum Einsatz. Das funktioniert über „@include“ und den Namen des Mixins.

Mixins einbinden

.box {
 @include box-shadow(0.1em 0.1em 0 rgba(0, 0, 0, 0.4));
}
.another-box {
  @include box-shadow(inset 0 0.2em 0.2em -0.15em rgba(0, 0, 0, 0.3));
}

Das Mixin generiert nun automatisch die entsprechenden Vendor-Prefixe. Soll später ein neuer Browser hinzukommen oder ändern sich die Prefixe, reicht ein Ändern des Mixins und das Generieren einer neuen CSS-Datei. Alle Vorkomnisse sind dann angepasst.

Zugriff auf Eltern-Elemente

Manchmal reicht die einfache Verschachtelung in die Tiefe nicht aus. Denn auch der umgekehrte Weg, also der Zugriff auf das übergeordnete Element, ist gelegentlich notwendig.

Herkömmliche Verschachtelung ohne Eltern-Zugriff

a {
 :link, :visited { ... }
 :hover, :focus { ... }
}

Das Ergebnis dieses Beispiels enthält ein unschönes Leerzeichen zwischen den Elementen im Selektor, was für die Definition von Links falsch ist. Mit dem Et-Zeichen (auch: kaufmännisches Und) fällt dieses Leerzeichen weg und der direkte Zugriff auf das Eltern-Element ist möglich.

Zugriff auf das Eltern-Element

a {
 &:link, &:visited { ... }
 &:hover, &:focus { ... }
}

In dieser Anwendung ist das nur wenig sinnvoll, da die ausgeschriebene CSS-Syntax kürzer ist als der SASS-Code. An anderer Stelle kann dieser Selektor aber durchaus hilfreich und sein Einsatz entsprechend nützlich sein.

Modernizr

Etwa beim Einsatz von Modernizr. Dieser erweitert das HTML-Element der Webseite um eine Vielzahl an Klassen, die anzeigen, welche modernen Funktionen der Browser mitbringt. Zum Beispiel weisen „.cssgradients“ oder eben „.no-cssgradients“ darauf hin, ob ein Browser Farbverläufe mit CSS unterstützt.

Hebt sich eine Box etwa nur durch einen Schatten vom Hintergrund ab, kann ein Fallback für ältere Browser notwendig sein. Hier kommt der Parent-Selektor mit dem "&" sehr gelegen.

Da der Eltern-Selektor an beliebiger Stelle einsetzbar ist, bleiben die Definition und das Fallback beisammen. Das hilft gerade in größeren Projekten mit vielen Frontend-Entwicklern oder bei solchen, die regelmäßige Wartung erfordern. In einer fernen Zukunft, in der Fallbacks wegen durchgängiger Browserunterstützung nicht mehr notwendig sind, entfernt man sie einfach wieder. Sie sind ja leicht zu finden.

Fallback dank Modernizr

.message {
 boxshadow: 1rem 1rem 1rem rgba(0, 0, 0, 0.5);
 .no-boxshadow & {
 border: 5px solid#CCC;
 }
}

Semantische CSS-Frameworks

Das größte Problem an CSS-Frameworks ist das Markup. Ob 960gs [3], YAML [4] oder eines der unzähligen anderen Frameworks – die nötigen CSS-Klassen im HTML-Code sind semantisch nicht sinnvoll und dienen ausschließlich der Präsentation. Denn die Klasse „.grid_2“ im 960gs sagt genausowenig über den Inhalt aus wie „.ym-col3“ in YAML.

Compass ergänzt SASS um viele praktische Funktionen.
Compass ergänzt SASS um viele praktische Funktionen.

Durch das Nutzen von SASS lässt sich das Frontend-Pferd andersherum aufzäumen. So lassen sich Klassen und IDs ganz nach eigenem Geschmack und gegebenem Inhalt vergeben und mit den (Grid-) Frameworks verknüpfen. Soll der Inhaltsbereich beispielsweise in einem Grid zehn Spalten einnehmen, so verzichtet man im Markup auf „<div class=„content grid_10“>“. Stattdessen bleibt es bei „<div class=„content“>“ und die entsprechenden Auszeichnungen werden über das Stylesheet zugewiesen.

CSS-Klassen einheitliche Namen zuweisen

.content {
 @include grid_10;
}

So bleibt das Markup sauber. Doch für jede Grid-Klasse eine SASS-Zuweisung zu schreiben, widerspricht der Logik geringeren Aufwands. Dank der Rechenfunktionen in SASS lassen sich diese aber auch in einem Mixin vereinen, das die Positionsberechnung durchführt.

Das folgende Beispiel ist natürlich sehr vereinfacht, es fehlen die Abstände zwischen den Spalten in der Berechnung und alles was sonst noch daran hängt. Doch dank derart dynamischer Berechnungen lässt sich etwa das Framework 960gs auf 100 Zeilen SASS eindampfen [5].

Ein einfaches Grid-System

$grid-width: 960px;
$num-columns: 12;
@mixin grid($column) {
 $column-width: $grid-width / $num-columns;
 width: $column * $num-columns;
}

Alternativ gibt es auch Grid-Systeme, die von Anfang an auf genau dieser Idee beruhen und direkt für die Nutzung mit Pre-Prozessoren entwickelt wurden, etwa Semantic.gs [6]. Diese Logik führt dann auch dazu, nicht mit Klassen in HTML zu gestalten, sondern stattdessen dort zu gestalten, wo es auch sinnvoll ist: in CSS.

Compass

Das auf 100 Zeilen SASS eingedampfte 960gs ist – zugegeben – kein pures SASS. Es handelt sich dabei um ein Compass-Plugin [7]. Compass ist ein CSS-Projekt-Framework; ganz im Gegensatz zu Layout-Frameworks wie 960gs. Projekt-Frameworks legen SASS sozusagen tiefer und schrauben Spoiler dran. Wofür? Um die Arbeit zu erleichtern.

Compass speichert dafür seine Einstellungen in einer Datei, der config.rb, im Wurzelverzeichnis des Projekts. Darin sind sämtliche Pfade zu relevanten Unterverzeichnissen, etwa dem für Bilder, CSS und JavaScript, abgelegt. So kann Compass direkter bei der Arbeit mit einem Projekt unterstützen, als dies ein einfacher CSS-Pre-Prozessor kann.

Mixins in Compass

Compass bringt bereits zahlreiche Mixins mit. Nach der Installation genügt deshalb ein „@import „compass“;“ am Dateianfang, um unzählige Mixins für zahlreiche CSS3-Funktionen nutzbar zu machen.

Egal ob „border-radius(3px)“, „box-flex(3)“ oder „background-size(100% auto)“ – um Prefixe kümmert sich fortan Compass. Entsprechend gilt die Faustregel, dass CSS3-Anweisungen in „@include anweisung(wert);“ umgeschrieben werden können. Die nötigen Vendor-Prefixe liefert Compass.

Verläufe in Compass

Einen Schritt weiter als das einfache Voranstellen von Browsernamen geht es bei der Nutzung von Verläufen in Hintergründen. Auch hier gibt es einige ältere Browser, die noch eine andere Syntax nutzen. Doch auch diese Variation übernimmt Compass. So lässt sich auch hier mit einer einfachen Schreibweise die Syntax aller Browser abdecken.

Hintergrund-Verläufe mit Compass

header {
 @include background(
 linear-gradient(top left, #333, #0C0),
 radial-gradient(#C00, #FFF 100px)
 );
}

Bilder mit Compass

Auch für in CSS genutzte Bilder hat Compass einige Funktionen im Gepäck. So ergänzt Compass etwa mit der Funktion „image-url('datei.png')“ Dateinamen um den richtigen Pfad, den es ja über die Konfigurationsdatei kennt. Das spart Tipparbeit und ermöglicht, das Verzeichnis auch nachträglich noch zu verschieben. Zugegeben, letzteres ist ein eher seltener Anwendungsfall. Trotzdem lohnt der Einsatz, denn außerdem hängt Compass einen Zeitstempel an den Bilderpfad, um die Probleme durch Browser-Caching zu minimieren.

Compass erlaubt es auch, Bildinformationen auszulesen. Um etwa eine Grafik im Hintergrund einzubauen, eignen sich die Funktionen zum dynamischen Auslösen von Breite und Höhe. Auf diese Weise lassen sich später Grafiken austauschen, ohne eine Änderung am CSS-Code vornehmen zu müssen. Das ist bei einzelnen Grafiken zwar ein wenig hilfreich, wirklich lohnenswert wird es aber beispielsweise bei einer Logoübersicht oder einer Bildergallerie.

Hintergrundbilder dynamisch einpassen

.logo {
 background: image-url('logo.png');
 width: image-width('logo.png');
 height: image-height('logo.png');
}

CSS-Sprites mit Compass

Bei einer CSS-Sprite werden viele kleine Bilder zu einem einzigen zusammengefügt und anschließend in CSS über Hintergrund-Positionen angesteuert. So wird nicht für jede einzelne Datei eine Verbindung zum Server aufgebaut und die Ladezeit der Webseite dadurch beschleunigt.

Doch wer schon einmal CSS-Sprites für sein Projekt angefertigt hat, weiß, wieviel Aufwand das ist. Und richtig viel Spaß machen Sprites, wenn nachträglich Icons mitten in der Sprite geändert oder ersetzt werden sollen oder sich Dimensionen verändern.

Hier springt Compass in die Bresche und erleichtert solche Anpassungen. Da das Bilderverzeichnis bekannt ist, landen CSS-Sprites, also alle Grafiken, die zusammengefasst werden sollen, einfach in einem Unterordner darin (im Beispiel „icon“). Nun kann Compass eine Sprite erstellen und die notwendigen Klassen im Stylesheet erzeugen. Der Aufwand: zwei Zeilen.

Sprites in Compass

@import 'icon/*.png';
@include all-icon-sprites();

Compass lädt nun alle PNG-Dateien aus dem icon/-Verzeichnis ins Sprite (erste Zeile) und fügt die entsprechenden Klassen hinzu (zweite Zeile). Angenommen, das Sprite besteht aus drei Bildern – new.png, edit.png und delete.png –, so sieht die CSS-Ausgabe der zwei Zeilen entsprechend aus.

CSS-Ergebnis der Compass-Sprites

.icon-sprite, .icon-delete, .icon-edit, .icon-new {
 background: url('/images/icon-sd26f725180.png') no-repeat;
}
.icon-delete {
 background-position: 0 0;
}
.icon-edit {
 background-position: 0 -16px;
}
.icon-new {
 background-position: 0 -32px;
}

Nun also doch wieder auferlegte Klassennamen, die vorher bei den Layout-Frameworks mühsam beseitigt wurden? Auf keinen Fall. Mit einem Mixin lassen sich die einzelnen Grafiken der Sprite mit eigenen Selektoren verwenden. Ändern sich im Projektverlauf die Grafiken, ist dann nicht mehr nötig, als die einzelnen Icons auszutauschen. Den Rest erledigt Compass.

Eigene Namen für Compass-Sprites

.new { @include icon-sprite(new); }
.edit { @include icon-sprite(edit); }
.delete { @include icon-sprite(delete); }

Auf die Kompilatoren, fertig, los

SASS und Compass können große Hilfen im Alltag sein. Sie dienen dazu, Projekte übersichtlicher zu gestalten und die Wartung zu erleichtern. Doch die angerissenen Themen sind nur einige Ausgangspunkte für die eigene Arbeit mit Pre-Prozessoren. Weitere Schritte können Farbberechnungen sein oder durch die Nutzung von Bedingungen und Schleifen komplexe und projektspezifische Frontend-Lösungen, die das Leben des gemeinen Frontend-Entwicklers deutlich erleichtern. Wie viele der zur Verfügung stehenden Funktionen er dabei nutzen möchte, bleibt natürlich jedem selbst überlassen. Einen Blick sind die neuen Möglichkeiten aber allemal wert.

Abonniere jetzt t3n-News über WhatsApp und bleib mobil auf dem Laufenden!
t3n-News via WhatsApp!
Vorheriger Artikel Zurück zur Startseite Nächster Artikel
Keine Antwort
Deine Meinung

Bitte melde dich an!

Du musst angemeldet sein, um einen Kommentar schreiben zu können.

Jetzt anmelden

Aktuelles aus dem Bereich CSS
Kein Umweg über Sass und Less: Chrome 49 bringt Unterstützung für CSS-Variablen mit
Kein Umweg über Sass und Less: Chrome 49 bringt Unterstützung für CSS-Variablen mit

Die kommende Version von Chrome wird endlich auch Custom Properties unterstützen. Damit stehen euch dann auch im Google-Browser CSS-Variablen zur Verfügung. » weiterlesen

Voxel.css: Das kann die quelloffene 3D-Library für das Web
Voxel.css: Das kann die quelloffene 3D-Library für das Web

Voxel.css ist eine leichtgewichtige 3D-Library auf Basis von CSS und JavaScript. Wir verraten euch, was es damit auf sich hat. » weiterlesen

Flexbox: Neuer Open-Source-Editor für den CSS-Layoutmodus
Flexbox: Neuer Open-Source-Editor für den CSS-Layoutmodus

Ein quelloffener Drag-&-Drop-Editor erlaubt es auch Nicht-Entwicklern Flexbox-Layouts zu erstellen. Wir haben uns das Tool für euch angeschaut. » weiterlesen

Alle Hefte Jetzt abonnieren – für nur 35 €

Kennst Du schon unser t3n Magazin?