10. April 2017 // von Stefan Pflaum

Stylesheets und Stylesheet Präprozessoren am Beispiel LESS

Die Anfänge

Das WWW ohne Stylesheets… das wäre eine immer gleiche und triste Ansammlung von HTML. Die Elemente jeder Website würden alle genau gleich aussehen:
Select-Boxen, Inputs, Buttons, Überschriften… einfach unvorstellbar, richtig?

Zum Glück haben Håkon Wium Lie und Bert Bos bereits 1994 zuerst unabhängig voneinander, dann zusammen an Cascading Stylesheets gearbeitet und schon 1995 wurde auch das W3C auf ihre Arbeit aufmerksam.

Zu dieser Zeit gab es natürlich auch andere Sprachen, die dasselbe Ziel verfolgten, doch Lie und Bos hatten als erste die Idee vom Vererben von Styles.

Diese Idee kam scheinbar sehr gut an, denn das W3C hat nur ein Jahr nachdem es von CSS erfahren hat die CSS Level 1 Recommendation publiziert. CSS war offiziell geboren!

Im Mai 1998 wurde CSS2 veröffentlicht und seit dem Jahr 2000 ist CSS Level 3 in der Entwicklung. CSS3 ist im Gegensatz zu seinen beiden Vorgängern modular aufgebaut, d.h. dass eine bestimmte Funktion in ein Modul ausgelagert wird, das dann unabhängig von anderen Modulen weiterentwickelt werden kann.
Dementsprechend kann man kein Datum der Veröffentlichung von CSS3 nennen, sondern nur seiner einzelnen Module, deren Entwicklung bis heute stetig fortgeführt wird.

Im September 2012 stellte das W3C klar, dass es kein CSS4 geben wird. Stattdessen werden die Module von CSS3 mit eigenen Versionsnummer immer weiterentwickelt.

CSS Preprocessors

Vergleicht man das Styling einer Website mit einem schicken Auto und betrachtet man CSS(3) als den Motor, dann ist ein CSS Preprocessor der Turbolader, die Lachgaseinspritzung und das Chiptuning in einem.

Damit ist gemeint, dass CSS Preprocessors herkömmliches CSS “erweitern” und nicht ersetzen. Das Zusammenspiel von CSS Preprocessors und CSS kann man mit PHP und HTML vergleichen:

Ein CSS Preprocessor hat seinen eigenen Syntax, der immer auf dem von CSS aufbaut. “Normaler” CSS Code funktioniert immer auch in den Files des Preprocessors, was CSS zum subset eines jeden CSS Preprocessors macht. In dem erweiterten Syntax geschriebener Code wird vom CSS Preprocessor abgearbeitet und letztendlich in herkömmliches CSS übersetzt, bevor die Antwort des Webservers an den Browser geschickt wird (ähnlich wie PHP in HTML übersetzt wird).

Dabei wird in der Regel natürlich nicht bei jedem Request gesondert compiliert, sondern bereits im Zuge des Deployment Prozesses. Das spart kostbare Zeit bei jedem einzelnen Seitenaufruf, da das Übersetzen in CSS selbstverständlich auch Rechenleistung in Anspruch nimmt. Während der Entwicklung wäre dieses Vorgehen allerdings hinderlich, da Änderungen am Style nicht vom Entwickler direkt eingesehen werden können. Deswegen nimmt man hier längere Ladezeiten in Kauf und lässt dafür bei jedem Request den (womöglich) geänderten Quellcode in CSS compilieren.

Dabei muss man, zum Glück, nicht mehr in die Shell des Webservers wechseln, um den Compilierungsprozess anzustoßen, sondern kann auf sehr hilfreiche Tools zurückgreifen, die einem diese Arbeit abnehmen.

gulp.js ist ein Beispiel für ein derartiges Helferchen. Mit Gulp kann man innerhalb einer Konfigurationsdatei im Root des Projekts nervige, immer wiederkehrende Aufgaben definieren, die Gulp dann selbstständig abarbeitet. Eine dieser Aufgaben könnte z.B. das Compilieren des CSS Preprocessor Quellcodes zu CSS sein oder das Zusammenfügen aller CSS Files in eine große minified File.

Doch warum das Ganze?

Durch den eigenen Syntax eröffnet ein CSS Preprocessor dem Entwickler ganz neue Möglichkeiten. So können z.B. bei den meisten Preprocessors Style-Schnipsel durch Funktionen (sog. “Mixins”) oder Imports von ganzen Files wiederverwertet werden. Das erspart dem Entwickler unnötigen Schreibaufwand und hält den Quellcode schön sauber.
Viele CSS Preprocessors bieten zudem die Möglichkeit an, Konstanten zu definieren. Dadurch können z.B. auf der gesamten Seite immer wieder auftretende Farben an einer Stelle als Konstante definiert werden, die dann an eben diesen Stellen referenziert wird. Dadurch muss man nicht den gesamten Quellcode durchsuchen, wenn sich die Farbe ändert, sondern muss nur die Definition der Konstante anpassen.

Natürlich bieten CSS Preprocessors noch viele weitere Funktionen, je nachdem, für welchen man sich bei seinem Projekt entscheidet. Grundsätzlich ist also ein CSS Preprocessor immer ein superset von CSS (alles andere würde nicht wirklich Sinn machen), d.h. der Preprocessor bietet immer alle Grundfunktionen von CSS und erweitert diese um eigene, oft für den Entwickler bequeme Zusatzfunktionen.

Wie viele CSS Preprocessors gibt es?

Jeder, der in der Schule, Ausbildung oder im Studium gezwungen wurde, reines CSS zu verwenden, weiß, wie mühselig das sein kann. Da liegt es natürlich nahe, sich das Leben mit einem Preprocessor leichter zu machen.

Weil aber die Geschmäcker von Entwicklern so unterschiedlich sind wie die farblichen Ausprägungen von Herbstlaub, kann man heute zwischen vielen verschiedenen CSS Preprocessors wählen, von denen jeder sein eigenes Verständnis von "hilfreich" und "bequem" hat. Die populärsten Beispiele sind wohl aktuell Sass, Stylus und Less. Wir bei Thomann haben uns für Less entschieden und nachfolgend wollen wir euch diesen CSS Preprocessor etwas detaillierter vorstellen!

Less

Less wurde 2009 von Alexis Sellier veröffentlicht. Sellier’s Ziel bei der Entwicklung war dabei, das Schreiben von CSS effizienter zu machen, indem man intelligente Steuerungen ermöglicht und Code-Wiederholungen vermeidet.

Dabei enthält Less viele der üblichen Funktionen von CSS Preprocessors, die auch bereits kurz angedeutet wurden. Nachfolgend wollen wir euch diese wirklich sehr hilfreichen Funktionen auch mit Codebeispielen näher erläutern.

Konstanten

Mit Konstanten können wir in Less immer wieder auftretende Werte für Styles an einer zentralen Stelle festhalten und, falls nötig, auch dort anpassen. Meistens werden so die Hex-Werte von Farben definiert, aber grundsätzlich sind hier auch Abstände, Background-Images und jeder andere Wert möglich.

Bleiben wir einfach bei einem der wohl gängigsten Beispiele in diesem Zusammenhang: der Farben. Während z.B. die Hover-Farbe oft überall auf der gesamten Website einheitlich ist, so wird sie in CSS leider meist an vielen mit ihrem Hex-Code neu gesetzt.
Über die Jahre gesehen kann es aber schon einmal vorkommen, dass ein junger und motivierter Grafiker, der womöglich neu im Projektteam ist, die gesamte Design-Ordnung öffentlich in Frage stellt und für eine neue Farbe des Hovers plädiert.

Den Entwicklern, die noch good ol’ CSS verwenden, steht jetzt der Angstschweiß auf der Stirn, denn Teile einiger ihrer zahlreichen CSS-Files sehen wie folgt aus:

main.css

a {
   color: #272727;
}

a:hover {
    color: #e27200;
}

article-list.css

.article-list .article-entry .name strong {
    color: #272727;
}

.article-list .article-entry .name strong:hover {
    color: #e27200;
}

header.css

header .navigation ul li {
    background: none;
}

header .navigation ul li:hover {
    background: #e27200;
}

Und das ist nur ein Auszug aus dem CSS-Durcheinander dieser Steinzeit-Entwickler. Nicht auszudenken, wie lange sie brauchen würden, um alle Stellen mit dem alten Farbcode zu finden und mit dem Neuen zu ersetzen (denn weil sie ja so oldschool sind, benutzen sie noch den Windows XP Text-Editor zum Coden und können nicht mit einer modernen IDE im gesamten Projekt nach dem Farbcode suchen).

Wären diese konservativen “früher war alles besser”-Entwickler mal lieber auf einen CSS Preprocessor wie Less umgestiegen!

Denn mit Less und seinen Konstanten ist eine solche Änderung kein Problem mehr. Anstatt an jeder möglichen Stelle den Farbcode auszuschreiben, verwendet man bei Less Referenzen auf eine Konstante, die oft einfach in einer zentralen File zusammen mit vielen anderen Konstanten definiert werden:

globals.less

@color-font: #272727;
@color-highlighted: #e27200;

Diese Konstanten können dann einfach in anderen Less-Files verwendet werden, sofern die globals.less dort importiert wurde... dank Gulp müssen wir uns aber auch darum nicht kümmern.

main.less

a {
    color: @color-font;

    &:hover {
        color: @color-highlighted;
    }
}

article-list.less

.article-list {
    .article-entry {
        .name {
            strong {
                color: @color-font;

                &:hover {
                    color: @color-highlighted;
                }
            }
        }
    }
}

header.less

header {
    .navigation {
        ul {
            li {
                background: none;

                &:hover {
                    background: @color-highlighted;
                }
            }
        }
    }
}

Jetzt ist die Änderung einer Schriftfarbe wirklich ein Klacks:

globals.less

@color-font: #272727;
@color-highlighted: #069fcb; // Thomann Blau!

Das wars! An jeder Stelle, die eine Farbe zum highlighten braucht, wird jetzt Thomann-Blau statt Orange verwendet! Selbst Schuld, wer hier noch mit vanilla CSS arbeitet…

Übrigens... Kein Big Deal aber trotzdem ganz schick: einzeilige Kommentare mit "//" wie in der aktualisierten globals.less sind durch Less nun auch möglich.

Verschachtelung

"Doch was sind das für komische Verschachtelungen in den Beispielen zu Konstanten? Das geht doch gar nicht mit CSS!"

Ganz genau! Auch das ist ein Feature, das wir durch einen Preprocessor wie Less nutzen können. Und es so unendlich hilfreich.

Manchmal geht es nicht anders: wir haben sehr verschachtelten HTML-Code auf unserer Website, bei dem es jetzt jedes Element zu stylen gilt, jede Menge Wiederholungen bei den Selectoren inbegriffen…

article.html

<div class="article">
    <a href="#">
        <img src="article-image.jpg">
    </a>
    <div class="info">
        <a href="#" class="name">
            <strong>
                Super Intrument
            </strong>
        </a>
        <strong>
            Beschreibung
        </strong>
        <p class="description">
            [...]
        </p>
        <ul class="bulletpoints">
            <li class="first">Super Klang</li>
            <li>Sehr pflegeleicht</li>
            <li>Bestes Preis-Leistungs-Verhältnis</li>
        </ul>
    </div>
</div>

Wenn man nun mit normalem CSS stylen möchte, ist man gezwungen, viele Selectoren mehrmals zu wiederholen:

article.css

.article .info strong {
    font-size: 15px;
}

.article .info .name strong {
    font-size: 22px;
}

.article .info .bulletpoints li {
    border-top: 1px solid black;
}

.article .info .bulletpoints li.first {
    border-top: none;
}

.article .info z.B. wird bei jeder der gezeigten Styles wiederholt. Für eine Ausnahme bei den Listenelementen der Bulletpoint-Liste müssen alle Selectoren der Listenelemente wiederholt werden. Das geht auch schöner!

Less bietet auch hier wieder eine Lösung:

article.less

.article {
    .info {
        strong {
            font-size: 15px;
        }

        .name {
            font-size: 22px;
        }

        .bulletpoints {
            li {
                border-top: 1px solid black;

                &.first {
                    border-top: none;
                }
            }
        }
    }
}

Durch das Verschachteln von Selectoren vermeidet man Wiederholungen und macht ganz nebenbei durch Einrücken des Codes die Struktur des HTML deutlich. Das sorgt für mehr Übersicht im Stylesheet für die Entwickler! Tolle Sache!

Mixins

Konstanten sind ja schon ziemlich nützlich, um das Kopieren von Code zu vermeiden. Allerdings können Konstanten nur Werte für Styles bereitstellen, keine ganzen Eigenschaft-Wert-Paare.

Das müssen sie aber auch nicht, da Less uns Mixins an die Hand gibt, die genau das und noch mehr können!

Widmen wir uns nun dem Thema, das so ziemlich jedem CSS-Anfänger den ein oder anderen Nerv gekostet hat: floating. Wenn sich die Elemente auf der Website plötzlich (scheinbar) völlig wirr anordnen, ist oft ein falsches oder nicht aufgelöstes Floating Schuld.

Dabei ist die Lösung meistens ganz einfach: ein Clearfix an der richtigen Stelle und schon werden Abstände und Anordnung von den Elementen wieder so eingehalten, wie der Web-Entwickler sich das vorgestellt hat:

.gallery img {
    display: inline-block;
    margin-right: 10px;
    float: left;
}

/* Hier ist der Clearfix */
.gallery:after {
    display: block;
    content: "";
    clear: both;
    float: none;
}

Obwohl die Elemente einer Bilder-Gallerie nach links floaten, werden durch den Clearfix keine nachfolgenden Elemente davon beeinflusst. Das funktioniert tadellos.

Aber was ist, wenn weiter unten ein Produkt-Carousel ebenfalls floatende Elemente enthält? Nun, dann kopieren wir den Clearfix einfach. Und bei den Navigation im Header? Einfach den Clearfix kopie…. Moment mal! Da muss es doch einen einfacheren Weg geben!

Den gibt es und er heißt in Less (und vielen anderen CSS Preprocessors) Mixins. Wie etwas weiter oben bereits erwähnt funktionieren Mixins so ähnlich wie die bereits vorgestellten Konstanten: sie geben uns die Möglichkeit, Code wiederverwerten zu können. Anders als Konstanten aber nicht nur einzelne Style-Werte, sondern ganze Blöcke!

globals.less

.clearfix() {
    &:after {
        display: block;
        content: "";
        clear: both;
        float: none;
    }
}

Der hier definierte .clearfix-Mixin bezieht sich durch das "&" auf das aktuell durch die Selectoren gewählte Element und fügt diesem den Clearfix hinzu.

Global definiert und einmal importiert, können wir ganz einfach an jeder beliebigen Stelle den Mixin aufrufen und so ein Floating auflösen:

.gallery {
    img {
        display: inline-block;
        margin-right: 10px;
        float: left;
    }

    .clearfix();
}

Es ist übrigens kein Zufall, dass Mixins im Syntax sehr viel Ähnlichkeit mit Funktionen haben, wie sie in den meisten Programmiersprachen verwendet werden. Mixins können genauso wie Funktionen auch Argumente akzeptieren. Das schaut dann wie folgt aus:

globals.less

.box-shadow(@color: #303030) {
    -moz-box-shadow: 1px 1px 5px 0 @color;
    -webkit-box-shadow: 1px 1px 5px 0 @color;
    box-shadow: 1px 1px 5px 0 @color;
}

Dem hier gezeigten Mixin .box-shadow kann ein Parameter @color mitgegeben werden, zurückgegeben wird ein an alle gängigen Browser angepasster Style-Block für die Darstellung eines Standard-Schlagschattens in der übergebenen Farbe.

Weitere Funktionen von Less

Natürlich ist Less nicht auf diese 3 Funktionen beschränkt sondern hat eine Vielzahl weiterer netter Features und kleinen oder großen Kniffen, die das Leben eines Entwickler redlich einfacher machen können.

Wir wollen hier aber nicht zu tief einsteigen in die Wunderwelt von Less... wer sich dafür interessiert, kann sich z.B. auf der offiziellen Website von Less informieren oder als Entwickler bei uns anfangen!

Zusammenfassung

Man kann wohl ohne Zweifel behaupten, dass Stylen ohne CSS Preprocessor einfach nicht mehr zeitgemäß ist. Obwohl man heutzutage mit einem regelrechten Überangebot an Preprocessors, die so ziemlich alle ihre Daseinsberechtigung haben, überhäuft wird, lohnt es sich x-fach, sich mit dem Thema auseinander zu setzen und nach dem richtigen Preprocessor für seinen Programmier-Stil und sein Projekt zu suchen.

Hat man sich für einen Preprocessor entschieden, dann genießt man die Arbeit mit diesem jeden Tag und kann sich gar nicht mehr vorstellen, mit langweiligem CSS3 arbeiten zu müssen…zum Glück haben wir bei Thomann uns schon vor relativ langer Zeit für Less entschieden!

Also fackel nicht lange und such dir deinen CSS Preprocessor, falls du noch keinen hast! Oder du bewirbst dich direkt bei Thomann und lernst von erfahrenen Profis, was Less alles zu bieten hat... die Entscheidung triffst du, ich habe meine schon vor vielen Jahren getroffen ;)

Verwandte Blogposts