8. Die objektorientierten Ansätze

Nicole Sullivan trat mit ihrem Ansatz “Object Oriented CSS” - kurz OOCSS - eine Lawine los. In ihrem Fahrwasser machten sich immer mehr Entwickler Gedanken über den richtigen Aufbau ihrer Stylesheets. Mit SMACSS und BEM entstanden zwei ebenfalls sehr einflussreiche Ansätze, die im Folgenden auch besprochen werden.

Die Argumentation geschieht dabei immer in Anlehnung an die objektorientierte Programmierung, obwohl es sich weder bei HTML noch bei CSS um eine Programmiersprache handelt. Möglicherweise wurde der Name mehr mit Gedanken an Marketing, als an Inhalte gewählt. “Module” wären der passende Begriff, nicht “Objekte”. Denn am Ende dreht sich alles um visuelle Muster, die im CSS abgebildet werden sollen.

OOCSS, SMACSS und BEM sind sich in ihrer Grundausrichtung ähnlich. Sie gehen alle mit einer leicht unterschiedlichen Sichtweise an die Sache heran, aber sie ähneln sich doch stark:

  • Die einzelnen Seitenelemente werden als Objekte betrachtet.
  • Seiten sind immer Zusammenstellungen mehrerer dieser Objekte und werden nie als Einheit betrachtet.
  • Alle Objektbestandteile werden mittels Klassen angesprochen.
  • Die Benamung der Klassen folgt einer rigide exekutierten Logik.
  • Alle Ansätze entstammen der Beschäftigung mit großen, komplexen Webseiten und komplexen Teams.
  • OOCSS und BEM gehen nur von Klassen als Selektoren aus, SMACSS verwendet zumindest hin und wieder Attributselektoren oder Elemente.
  • Die Nutzung von IDs ist verpönt, quasi verboten.

Allen Ansätzen halte ich zu Gute, dass sie den Blick auf wichtige Details geschärft haben, dass sie einen Ansatz liefern, mit immer komplexer werdenden Stylesheets umzugehen. Sie bieten eine Basis für die Entwicklung eigener Best Practices. Als solches sollte man sie sehen, nicht als heilige Schrift. Leider ist Letzteres zu oft der Fall.

Objektorientiertes CSS und Semantik

Der Fokus der im Folgenden diskutierten Ansätze liegt immer auf der Organisation und Schreibweise des CSS. HTML wird dabei eigentlich immer vernachlässigt. Das führt in der uninformierten, undurchdachten Anwendung gerne dazu, dass die Semantik vernachlässigt wird. So entstehen unnötige DIV-Wüsten und die Existenz des button-Elements scheint in Vergessenheit zu geraten. Schliesslich können die passenden Styles jedem beliebigen Element mit der passenden Klasse gegeben werden. Ein wenig JavaScript macht dann auch ein span-Element interaktiv.

Die objektorientierten Ansätze propagieren eine gewisse Form der Abstraktion. Diese gilt für das CSS. Sie sollte nicht für das HTML gelten. Das HTML sollte auch ohne CSS noch Sinn ergeben und ist von BEM und Konsorten unbeeindruckt.

OOCSS

Unter dem Eindruck allzu umfangreicher Stylesheets in Großprojekten entwickelte Nicole Sullivan den Ansatz OOCSS. Das Ziel war die bessere Skalierbarkeit, vor allem in großen Teams. Dafür suchte sie nach Wiederholungen, Mustern und leicht korrigierbaren Abweichungen in den Styles der einzelnen Module.

Sullivan trennte dann Basis-Styles für Module von Designinformationen, die eventuell modulübergreifend nutzbar sind. Zusätzlich trennte sie Designinformationen von Semantik, indem sie komplett auf die Verwendung von Klassen baute, anstatt Elementselektoren zu nutzen. Das führt zu zwei einfachen Regeln:

  1. Trenne Struktur und Darstellung.
  2. Trenne Container (des Moduls) und Inhalt.

Im Gegensatz zu den nachfolgenden Konzepten ist OOCSS recht einfach und schmal. Es macht mehr den Eindruck einer durchdachten Skizze. Es gibt bspw. keine Nomenklatur für Klassennamen. Lange Zeit gab es wenig Implementierungsbeispiele. Mittlerweile ist das Projekt gewachsen, wenn auch immernoch übersichtlicher, als die anderen Protagonisten.

OOCSS lässt sich auf einige wenige Klassen eindampfen, die global nutzbar sein sollen. Eine Modulklasse, bei Sullivan beispielhaft .mod genannt, beinhaltet optionale Elemente mit den Klassen .hd (Header), .bd (Body) und .ft (Footer). Diese Elemente werden dann noch in einen Wrapper namens .inner gepackt. Dieser erklärt sich aus der Entstehungszeit. Denn um 2006 herum waren die alten IE noch sehr verbreitet, die Kunden wollten aber trotzdem auch für diese die beliebten runden Ecken haben. Den .inner-Container benötigte Sullivan also primär als zusätzlichen Hook, um Bilder für runde Ecken zu platzieren. Mit modernen HTML5-Elementen könnte das idealtypische OOCSS-Modul also folgendermaßen aussehen:

 1 <div class="mod">
 2   <header class="hd">
 3     <h3>Tolle Headline</h3>
 4   </header>
 5 		<div class="bd">
 6       <p>Toller Inhalt</p>
 7 		</div>
 8     <footer class="ft">
 9     Was auch immer hier stehen soll
10   </footer>
11 </div>

Sullivan verortet die Klassen bewusst auf DIV-Elemente, die als Wrapper für die eigentlichen Inhalte dienen. Sie rät bewusst davon ab, Elementselektoren in CSS-Regeln mit aufzunehmen. Dann dadurch gibt es eine Abhängigkeit des CSS vom eingesetzten HTML und die Spezifität der Regeln verändert sich.

Da wir im Gegensatz zur Entstehungszeit von OOCSS mittlerweile über neue HTML5-Elemente verfügen und alle modernen Browser die grundlegenden CSS3-Eigenschaften beherrschen, dürfte auch Nicole Sullivan nichts dagegen haben, wenn wir die Klasse .hd direkt an die Überschrift setzen und uns so eine DOM-Ebene sparen. Ob wir einen zusätzlichen Wrapper benötigen kann schlicht vom zu erreichenden Design abhängen.

Eine weitere schöne Idee von Sullivan war, Abweichungen im Design eines Moduls durch Modifikatoren zu realisieren. Das Modul kann also auch folgendermassen aussehen:

1 <div class="mod light">
2   <h3 class="hd">Tolle Headline</h3>
3   <p>Toller Inhalt</p>
4 </div>

Die Klasse .light sorgt dafür, dass das Modul abweichend von der normalen Formatierung aussieht. Ich empfehle, regen Gebrauch von solchen Modifikatoren zu machen und diese dabei im Wesentlichen immer nur eine Eigenschaft modifizieren zu lassen. Sie sind dann im Einsatz flexibler. Wenn Sie also Hintergrundfarbe, Rahmen und die Floatrichtung eines Bildes modifizieren wollen, dann schreiben Sie für jede diese Änderungen eine separate Klasse.

Am Ende können drei oder mehr Modifikatoren eine Klasse ergänzen. Das ist kein Problem. Wir selber verlieren sehr viel schneller die Übersicht, als der Browser vor der Masse der Klassen einbricht. Irgendwann nach 2000 Klassen ist bei den IEs eine Grenze. Wir haben schon viel früher die Übersicht verloren. Deshalb spricht nichts dagehen, ein Modul mit fünf oder zehn Modifikatoren zu ergänzen und so sparsames CSS zu schreiben.

SMACSS: Unterschiedliche Einzelteile des CSS

Jonathan Snook nimmt mit seinem Ansatz SMACSS - Akronym für Scalable and Modular Architecture for CSS - eher eine Dokumentenperspektive ein. Er analysiert die unterschiedlichen Einsatzzwecke für CSS und kategorisiert dadurch seine Styles. Obwohl auch Snook Webseiten als Ansammlung von Modulen betrachtet, sieht er mehrere wichtige Ebenen, nicht nur die der Module. Folgende fünf Bereiche werden identifiziert:

  1. Base
  2. Layout
  3. Module
  4. State (Zustand)
  5. Theme

Base-Styles sind die Reset- oder Normalisierungs-Styles eines Projekts. Bei den Layout-Styles handelt es sich üblicherweise um ein Grid- oder Spaltensystem. Die Module werden in Aufbau und Gestaltung beschrieben. Die State-Styles sind Regeln, die für den Zustand eines Moduls zuständig sind. Also beispielsweise die Gestaltung eines geöffneten bzw. geschlossenen Items in einem Akkordeon.

Mittels Theming kann man einem Projekt eine andere Identität geben und so aus einer einzigen Basis mehrere Kundenprojekte kreieren. Im Grunde kann man den optischen Eindruck als Theming sehen. Trennt man dies vom Rest der Regeln, hat man ein Set an Gestaltungsregeln, die man gezielt manipulieren kann, um einen veränderten Eindruck zu erwecken.

Snook führt in seinem Ansatz auch Namenskonventionen ein. Diese erleichtern die Zuweisung von Styles zu einem der oben genannten fünf Bereiche. So werden State-Styles mit .is- oder .has- begonnen, Layout-Styles haben .l- oder .layout- als Prefix. Module hingegen bekommen keinen Prefix, stehen für sich.

Ich finde SMACSS sinnvoll, um sich die Eigenarten eines Projektes und die unterschiedlichen Aufgabenbereiche der Gestaltung klar zu machen. Auch die Prefixes für State-Styles finde ich sehr praktisch.

BEM (Block, Element, Modifier)

Von der russischen Suchmaschine Yandex stammt der Ansatz BEM. Das Akronym steht dabei für “Block, Element, Modifier”. Ein Modul einer Webseite wird als “Block” bezeichnet. Dieser besteht wiederum aus mehreren Elementen. Die Darstellung dieser Elemente kann durch “Modifier” verändert werden.

In der Doku wird eine Navigation als Beispiel genommen. Die Navigation selber ist hierbei der Block. Die einzelnen Links - egal wie sie gestaltet sind - sind die Elemente. Die Formatierung als vertikale oder horizontale Navigation, als Reiter oder Buttons, geschieht dann über die Zuweisung der passenden Modifier.

Wir haben also eine Trennung zwischen Grundstyles und Modifikationen. Auch der BEM-Ansatz geht davon aus, dass wir kein komplett neues Modul benötigen, nur weil es anders aussieht, als ein in der Struktur ähnliches oder gleiches.

Insbesondere die BEM-Nomenklatur hat in der letzten Zeit viele Fürsprecher gefunden. Anscheinend besticht ihre schlichte und strikte Logik. Die dadurch entstehenden langen Klassennamen scheinen nicht alle Entwickler abzuschrecken.

Die drei Bestandteile des BEM-Ansatzes werden sauber durch die Benennungsregeln identifizierbar. Dabei werden doppelte Binde- und Unterstriche genutzt. Die Grundidee ist Folgende:

1 .block {}
2 .block__element  {}
3 .block--modifier {}
4 .block__element--modifier {}

In einem praktischen Beispiel kann das dann so aussehen:

1 .speech-bubble{}
2 .speech-bubble__header{}
3 .speech-bubble__text{}
4 .speech-bubble__text--link{}

Die einzelnen Elemente und Modifier werden im Grunde genommen mit dem Namen des Moduls als Namespace versehen. Das passiert, um eine niedrige Spezifität zu bewahren. Doch genau mit dieser Begründung habe ich mein Problem.

Es macht für mich im Endergebnis keinen Unterschied, ob eine Regel eine hohe oder niedrige Spezifität hat, wenn ich diese Regel sowieso nur auf einen kleinen, begrenzten Einsatzzweck beschränken möchte. Für den Erfolg einer Arbeit ist es unerheblich, ob im CSS .speech-bubble__header {} oder .speech-bubble .header {} steht. Weder im CSS noch im HTML benötigen wir die Pseudo-Namespaces, um eine Zuordnung machen zu können. Im HTML stehen die Elemente direkt innerhalb des Moduls, im CSS gruppiert man sinnvollerweise alle zu einem Modul gehörenden Styles an einem Ort. Nutzt man einen Präprozessor, wird dies durch Verschachtelung vereinfacht.

Die höhere Spezifität meines Alternativbeispiels ist unerheblich, denn das Ergebnis ist das Gleiche. Da ich meine Elemente nicht mit einem Modulprefix versehe, kann ich sie in unterschiedlichen Modulen nutzen. Da ich die Klassen der Elemente aber im Kontext der Modulklassen aufrufe, wirkt dies so, als hätte ich ein Modulprefix gesetzt.

Bei BEM wird eine Klasse nur innerhalb eines Moduls genutzt. Die mehrfache Nutzung einer Klasse innerhalb verschiedener Module ist nicht vorgesehen, schliesslich arbeiten alle Klassen mit einem Modulprefix.

Bei beiden Vorgehensweisen gibt es keine Konflikte. Beim von mir vorgeschlagenen Vorgehen kann ich hingegen sogar Gemeinsamkeiten auslagern.

Im Endergebnis muss man bei BEM immer mit langen und noch längeren Klassennamen umgehen. Dabei ist der lange Klassenname, der einmalig im Kontext eines Moduls genutzt wird, auch nicht besser als ein allgemeinerer Name, der in mehreren Modulen genutzt wird, aber nur im Kontext des Moduls gestaltet wird.