Du hast deinen AdBlocker an?

Es wäre ein Traum, wenn du ihn für t3n.de deaktivierst. Wir zeigen dir gerne, wie das geht. Und natürlich erklären wir dir auch, warum uns das so wichtig ist. Digitales High-five, deine t3n-Redaktion

t3n 34

Nützliches Schubladendenken: Mit modularem CSS den Überblick behalten

Modulares CSS. (Foto: Tiberiu Ana / Flickr Lizenz: CC BY 2.0)

CSS ist einfach. Die Regeln sind schnell erlernt und es ist sofort einsatzbereit. Deutlich schwieriger ist es indes, bei großen Projekten den Überblick zu behalten. Doch dafür gibt es Tipps, Tricks und meist mehr als einen Weg zum Ziel. Wir stellen Best Practices für schnelles, übersichtliches und wartbares CSS vor.

Sauberes HTML und ordentliches CSS sind möglichst kurz und selbsterklärend. Jahrelang dieses Mantra: Möglichst wenige Klassen; kurze, prägnante Namen; keine unnötigen Dopplungen. Bis zu einem gewissen Grad funktioniert das auch ziemlich gut. Zumindest bei relativ kleinen Websites.

Schwieriger wird es bei größeren Projekten, beim Einsatz von vielen Templates, bei einer Web-App oder einer Konzern-Website. Außerdem stößt dieses Konzept bei Projekten an seine Grenzen, bei denen mehr als ein Entwickler beteiligt ist. Und bei allem, was auf lange Sicht weiterentwickelt und gepflegt werden soll.

Auch semantische Klassennamen, also selbsterklärende Bezeichnungen, sind in vielen Fällen eine Wunschvorstellung, die oft mehr Probleme erzeugen als sie lösen. So mag die Klasse „.news“ problemlos funktionieren und ein Blick in den Code zeigt jedem, dass hier Neuigkeiten formatiert werden. Was passiert aber, wenn auf einer zweiten Seite eine Ausgabe von Terminen erfolgt, die in weiten Teilen jener der Neuigkeiten entspricht? Entweder werden fortan mehrere „.news“-Klassen oder schlichtweg mehr CSS-Code benötigt.

Konventionen

Gerade für die Arbeit im Team ist deshalb eine umfangreiche Konvention unerlässlich. Eine gute Basis dafür sind „fertige Systeme“, BEM oder SMACSS sind zwei solche Kandidaten. In weiten Teilen überschneiden sich diese in ihren Ideen beziehungsweise sind der Grundlage von Twitter Bootstrap ähnlich.

Noch wichtiger als das Festlegen dieser Konventionen ist aber das Einhalten. Das klingt offensichtlich und logisch, aber die Belastungsprobe kommt, sobald aufgrund nahender Deadlines mal eben eine kleine Änderung vorgenommen werden muss oder ein neuer Entwickler ins Team kommt.

Modularität

In der Umsetzung eines mitwachsenden Frontends sollten möglichst große Teile abstrahiert und zusammengefasst werden. Das sichert einerseits Konsistenz im Aussehen, andererseits hält es den Code für das Frontend klein, übersichtlich und gut wartbar. Außerdem sollten Module von ihrer Umgebung unabhängig sein. Egal, ob das Modul im Inhaltsbereich der Website auftaucht, in der Sidebar oder gar in sich selbst – ein Modul sollte möglichst in jedem Kontext der Website funktionieren.

Ein gutes Beispiel für eine solche Modularisierung ist das Media-Object Nicole Sullivans für Facebook. Dem Frontend-Team bei Facebook war der eigene Code über den Kopf gewachsen, viele Dinge waren an unzähligen Stellen doppelt und dreifach definiert. Die daraus resultierende Angst, etwas an dem bestehenden Code zu ändern und damit unvorhergesehene Nebeneffekte auszulösen, kennen viele Entwickler nur zu gut. Der erste Impuls wäre es jetzt, einfach einen neuen, spezifischeren Selektor hinzuzufügen und den Code so noch unübersichtlicher zu machen.

Einsatzmöglichkeiten für den CSS-Code aus dem Media-Objekt.
Einsatzmöglichkeiten für den CSS-Code aus dem Media-Objekt.

HTML-Markup des Media-Objects

<div class="media">
  <a href="" href="" class="img">
    <img xsrc="" xsrc="" />
  </a>
  <div class="bd">
    Lorem ipsum
  </div>
</div>

Listing 1

Sullivans Ansatz, um dieses Problem in den Griff zu bekommen, war es hingegen, wiederkehrende Muster zu entdecken und zusammenzufassen. Ein solches Muster fand sie in der Darstellung eines Bilds neben einem Textblock variabler Größe: Profilbilder neben Statusmeldungen, kleinere Profilbilder neben Kommentaren, Icons neben Links, Bilder neben Anzeigen.

Der Code ist ein paar Jahre alt und einige Dinge, etwa den Clearfix oder die Abstände, würde man heute sicher anders umsetzen, aber die Grundidee bleibt die Gleiche: Mit diesen wenigen Zeilen Code konnten hunderte Zeilen alter Code abgelöst werden. Kaum eigener Code für Statusmeldungen, Kommentare, Anzeigen oder Icon-Links ist mehr nötig.

Media-Object-CSS

.media {margin:10px;}
.media, .bd {overflow:hidden; _overflow:visible; zoom:1;}
.media .img {float:left; margin-right: 10px;}
.media .img img{display:block;}
.media .imgExt{float:right; margin-left: 10px;}

Listing 2

Ein weiterer Vorteil ist der weitgehende Verzicht auf das direkte Styling von HTML-Elementen. Durch die Klassen kann im Prinzip jedes semantische Markup in die Form des Media-Objekts gebracht werden. Egal ob (wie hier) mit <div>-Containern, Überschriften, Absätzen oder sonstigen Auszeichnungen. So müssen bei jedem Vorkommen nur noch eventuell erforderliche Abweichungen hinzugefügt werden.

Die bereits genannten modularen Systeme SMACSS und BEM fügen den Modulnamen jeweils in die Klassen ein. Demnach ist bereits beim Lesen der Selektoren klar, zu welchem Modul diverse Code-Segmente gehören. Bei SMACSS würden Selektoren des Media-Moduls entsprechend mit dem Präfix „media“ versehen werden.

SMACSS-Äquivalent zum Media-Object

.media {}
.media, .media-body {}
.media-image {}
.media-image img {}
.media-meta {}

Listing 3

Das ist besonders dann hilfreich, wenn ein HTML-Element Klassen verschiedener Module hat. So könnte ein <div> beispielsweise gleichzeitig der Wrapper unseres Media-Moduls sein und eine „.box“-Klasse besitzen, um einen Rahmen oder eine Hintergrundfarbe zu bekommen.

Submodule

Ganz ähnlich bei Buttons: In einem eigenen Modul definiert die Klasse „.button“, wie ein Standard-Button auf der Website aussieht. Da an manchen Stellen Varianten davon existieren, etwa für den standardmäßig gewählten oder den Löschen-Button, gibt es erweiternde Klassen. Das CSS sieht exemplarisch folgendermaßen aus:

Button-Modul

<button class=„button button-primary“>Text</button>

Listing 4

Mit Blick auf das entsprechende HTML-Element stellen sich nun bei manch einem möglicherweise die Nackenhaare auf, denn immerhin ließe sich eine Klasse „.primary“ auch als Erweiterung von „.button“ definieren. Sie würde dann über „.button.primary“ angesprochen, was Code spart. Alternativ ließe sich der Button auch über das HTML-Element <button> selbst ansteuern, was Code und eine CSS-Klasse erspart.

Entsprechender CSS-Code

.button {
  color: gray;
  border: 0.1em solid #333;
}
.button-primary {
  color: blue;
}

Listing 5

Doch das Erweitern von Elementen verteilt Klassen an verschiedene Stellen im Code, was leicht unübersichtlich wird und entsprechend vorsichtig eingesetzt werden sollte. Außerdem lassen sich so Teile aus verschiedenen Modulen besser kombinieren. Dem Button die Klasse „.button“ zu geben hat zudem den Vorteil, dass sich andere HTML-Elemente ebenfalls wie ein Button gestalten lassen – obwohl sie möglicherweise Links oder Input-Submits sind. Der Code wird also wiederverwendbar.

Etwas schwieriger wird es bei Modulkombinationen, etwa wenn man alle Buttons in Teaser-Boxen anders darstellen möchte, so dass das Button-Modul bei Verwendung im Teaser-Modul anders aussehen würde. Vor der Auflösung der bislang sauberen Trennung einzelner Module, stellen sich nun zwei Fragen:

  • Ist diese System-Abweichung notwendig?
  • Ist diese Anpassung auch abseits dieser speziellen Modulkombination notwendig?

Müssen die Buttons also vielleicht gar nicht anders sein? Solche Inkonsistenzen treten häufig dann auf, wenn Designer und Entwickler nicht dieselbe Person sind. In so einem Fall sollte mit dem Designer geklärt werden, ob die Abweichung bewusst und unbedingt notwendig ist. Die Erfahrung zeigt, dass Designer für solche Hinweise oft dankbar sind und das Argument der Konsistenz und Einheitlichkeit, also der durchwegs gleichen Eigenschaft der Buttons, meist gut nachvollziehbar ist.

Das Ziel sollte sein, den geschriebenen Code möglichst gut und oft wiederverwerten zu können. In der Regel ist es in einem solchen Fall besser, das neue Aussehen als zusätzliches Element in das Button-Modul aufzunehmen. Modulüberschreitende Selektoren wie „.teaser .button“ sind selten eine gute Idee. Besser ist es, dem Button eine zusätzliche Klasse zu geben und so die Modifikation zu steuern: <a class="button button-big">. Auf diese Weise ist es ein Leichtes, auch dem Kontaktformular plötzlich den großen Button zu geben.

Die Kaskade ausnutzen

Kaskade bedeutet Wasserfall und genau der hilft beim Schreiben von CSS. Die Entscheidung, welche CSS-Definitionen auf ein Element angewendet werden, entscheidet sich dadurch, wie spezifisch der Selektor ist. Die Grundregeln: Eine Klasse schlägt ein Element, zwei Klassen schlagen eine Klasse, eine ID schlägt Klassen und das Style-Attribut schlägt die ID. Dieses wiederum wird nur durch „!important“ geschlagen.

Das ist primär nötig, damit sich Module gegenseitig überschreiben können. Entsprechend sind diese Spezifikationen im Idealfall immer und genau so umgesetzt – in der Praxis leider sehr schwierig.

Weniger Ebenen sind dabei besser. Da die einzelnen Klassen aber ohnehin mit dem Modulnamen versehen sind, werden die Selektorketten automatisch kürzer. Im Zweifel ist fast immer eine weitere Modifikator-Klasse am Element einer längeren Selektorkette vorzuziehen. Letzteres wirkt sich im Übrigen auch positiv auf die CSS-Performance aus.

Die Möglichkeit einzelner Module, einander zu überschreiben, ist ein Grund, warum eine ID in CSS-Selektoren vermieden werden sollte. Denn wenn einmal der ID-Vorschlaghammer ausgepackt wurde, benötigt das nächste Modul noch schwereres Gerät und muss mit der !important-Abrissbirne zu Werke gehen. An diesem Punkt ist jede Kaskade verloren. Und „!important“ sollte nicht häufiger eingesetzt werden, als der Royal Flush beim Poker vorkommt – einmal in rund 650.000 Runden.

Präprozessoren

Sass, Less oder Stylus sind weitgehend bekannt. Bis zu welchem Grad und ob diese überhaupt eingesetzt werden, muss jeder für sich entscheiden. Aber gerade die Aufteilung einer CSS-Datei in mehrere Teil-Dateien hilft ungemein, den Überblick zu behalten: So lassen sich die Darstellung der HTML-Elemente vom Grundlayout und dem Styling der Inhalte trennen.

Mögliche Teildateien des Projektes.
Mögliche Teildateien des Projektes.

Bei umfangreicheren Projekten kann es sinnvoll sein, einzelne Module ebenfalls auf eigene Dateien aufzuteilen. Variablen für Farben, Typografie und wiederkehrende Abstände lassen sich ebenfalls in einer eigenen Datei sammeln, um später Anpassungen an zentraler Stelle vornehmen zu können. Gleiches gilt für Mixins und Platzhalter-Definitionen („Silent Classes“). Diese Datei kann dann auch problemlos von Projekt zu Projekt mitgenommen und überall eingefügt werden. So entwickelt sich nach und nach ein eigenes kleines Frontend-Framework.

Fazit

Mit einem modularen Aufbau des CSS-Codes ist ein guter Grundstein gelegt, die Übersicht zu behalten und ein gutes und schnelles Frontend zu entwickeln. Selbiges lässt sich über einen langen Zeitraum pflegen und weiterentwickeln, ohne Knoten im CSS zu erzeugen. Empfohlen sei an dieser Stelle auch das offizielle SMACSS-Buch, das die modularen Gedanken etwas tiefgehender erklärt.

Zuletzt bleibt die Empfehlung, einen strikt modularen Aufbau schlicht einmal auszuprobieren. Anfangs etwas ungewohnt, zeigen sich die Vorteile ziemlich schnell. Umso stärker, je größer das Projekt ist. Zumindest, wenn man konsequent dabei bleibt.

Andreas Dantz
Andreas Dantz

ist Designer und Frontend-Entwickler bei der von ihm gegründeten Agentur Vortrieb. Dort hilft er Kunden jeder Größe, erfolgreiche Web-Projekte umzusetzen.

Bitte beachte unsere Community-Richtlinien

Schreib den ersten Kommentar!

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

Jetzt anmelden