senäh

17senäh und so…

CSS Best Practices Artikelbild

HTML/CSS/JS
12. Apr 2012
Kommentare: 1

CSS: Best Practices in einer Zeit gegensätzlicher Entwicklungen

Kategorien: HTML/CSS/JS | 12. Apr 2012 | Kommentare: 1

CSS kennt ihr. Ihr habt sicher auch ein in jahrelanger Schweißarbeit eigenentwickeltes Schema, nach dem ihr eure CSS-Dateien aufbereitet und formatiert ;). Nun gibt es da aber etwas Neues am CSS-Entwicklungshimmel, das nennt sich objektorientiertes CSS. WTF?

Es handelt sich nicht um wirkliche Objektorientierung im klassischen Sinne. Begriffe wie Klassen und Vererbung findet man zwar auch im CSS-Sprachjargon vor, allerdings mit einer anderen Bedeutung.

Objektorientiertes CSS (OOCSS) meint eher die Orientierung an Wartbarkeit und wiederverwendbarem Code. So sollen positionsabhängige Selektoren (z.B. section:first-child oder p:nth-child(odd)) vermieden werden.

Der Grund? Im nächsten Projekt will man vielleicht eine bestimmte CSS-Komponente leicht abgewandelt wiederverwenden. Jedoch findet man ein mitunter komplett anderes Layout vor und damit einhergehend oft auch anderes HTML-Markup. Positionsabhängige CSS-Styles lassen sich also in den meisten Fällen nicht 1:1 übertragen. Schlecht.

Stattdessen soll man auf Klassen zurückgreifen. Klassen, Klassen, Klassen. Dabei wird auch noch zwischen strukturellen (z.B. header) und dekorierenden (z.B. blue-border) Klassen unterschieden.

Das ist die Basis von OOCSS: Klassen statt positionsabhängigen Styles für bessere Wiederverwendbarkeit. Modularisierte Styles sollen die Entwicklungszeit verringern und ein Projekt flexibler gegenüber späten Änderungen machen. Nachvollziehbare Vorteile.

Und was meint er mit gegensätzlichen Entwicklungen?

Entwicklung #1 habe ich gerade vorgestellt: OOCSS. Gegen die dabei zur Anwendung kommenden Prinzipien sprechen allerdings andere aktuelle Erscheinungen. Konkret meine ich neue Selektoren dank CSS3 und die ausschließliche Verwendung semantischer Klassennamen.

Warum gegensätzlich?

Während CSS3 positionsabhängige Selektoren einführt, will OOCSS uns von diesem Teufelszeug wegbringen. Während Chris Coyier immer und immer wieder von der Bedeutung von Semantik spricht, hat OOCSS nichts gegen unsemantische Klassennamen. Ich denke die Gegensätze werden deutlich.

Der letzte Punkt ist vielleicht nicht sofort verständlich, wenn man nicht im Thema steckt. Deswegen gehe ich kurz (haha, Enno und kurz…) darauf ein.

Das Problem der Klassennamen

Es geht darum, dass Klassennamen eine Gruppe von Elementen zusammenfassen sollen. Sie sollen allerdings nicht das Aussehen bzw. Styling beschreiben.

Es folgen Beispiele. Semantische Klassennamen sind:

  • call-to-action-button
  • error-msg; “msg” für “Message” 😉
  • alert
  • additional-info.

Unsemantische Klassennamen dagegen sind:

  • left
  • hidden
  • yellow-background
  • more-padding.

Der Unterschied wird deutlich oder? Es geht darum, dass das HTML-Markup lediglich Semantik beinhaltet. Nicht nur unnötige Tags sollen vermieden werden, sondern auch unnötige Klassennamen. Wie gesagt: Klassen sollen keine (oder abgemildert: nicht nur) Hilfe für Stye-Angaben sein sondern müssen Gruppierungen von gleichartigen Elementen darstellen.

Was tun mit unsemantischen Klassennamen?

Nachdem ihr jetzt wisst, was ich meine, und euch natürlich direkt vornehmt, never ever again unsemantische Klassennamen zu verwenden, müssen wir die alten Gewohnheiten kompensieren.

Der geneigte Unsemantik-Junkie wird sich jetzt direkt dabei erwischen, wie er panisch daran zweifelt in Zukunft überleben zu können. Vermutlich stellt er sich mehrfach folgende Frage: wie benenne ich meine Klassen so um, dass ich in den Semantik-Himmel komme?

Ich halte mich immer an folgende Faustregel: Wenn dir kein semantischer Klassenname einfällt, gibt es keinen.

Das bedeutet nicht, dass ich nur so vor Allwissenheit strotze. Vielmehr gehe ich davon aus, dass eine Gruppenzugehörigkeit, die wir ja bei semantischen Klassennamen suchen, recht schnell zu erfassen ist. Wenn man also keine findet, handelt es sich um einfache Style-Anweisungen, die nichts im HTML verloren haben. Weder als Inline-Styles, noch als CSS-Klasse.

Die Lösung: ortsabhängige Styles. Wir verzichten auf eine Klasse und fügen die Styles stattdessen ortsabhängig ein. Wenn ich also ein Element verstecken möchte, ohne die Klasse hidden zuzuweisen, dann schreibe ich die entsprechende Anweisung display:none als ortsabhängigen Style in die CSS. Ortsabhängig – zur Wiederholung – meint in diesem Fall sowas wie #header div.additional-info > p. Das p-Tag wird durch seine Position angesprochen, nicht durch eine ID oder eine Klasse. Darum „ortsabhängiges Styling“.

Daraus ergibt sich allerdings wiederum ein offensichtliches Problem.

Vom vorübergehenden Bruch mit dem DRY-Prinzip

CSS-Klassen haben wir bisher verwendet um mehreren Elementen dasselbe Styling zukommen zu lassen. Hatte ich bisher eine unsemantische Klasse namens left für links-floatende Elemente, habe ich diese allen Elementen zugewiesen, die links floaten sollen. Logisch.

Wenn ich mich aber jetzt mit meinem neugewonnenen Lebensmut von allem Nicht-Semantischen verabschieden möchte, werde ich die Klasse left nicht verwenden. Stattdessen muss ich an allen relevanten Stellen die Anweisung float:left explizit notieren, notfalls auch mehrmals.

Was sagt er? Mehrmals?!?
Was ist mit DRY (Don’t repeat yourself)?

Ja, wir notieren identische Styles mehrfach. Das macht unseren Code schwerer wartbar und erzeugt unnötig viel Daten, die es zu übertragen gilt. Wollten wir nicht genau das verhindern?

Ja. Deswegen ist dieser Zustand auch nur vorübergehend. Also bitte, nicht so ungeduldig 😉

Lösung: CSS Preprocessors – und nein, ich werde nicht sowas wie Präprozessoren sagen 😉

Jawoll. Unser Allheilmittel sind die sogenannten CSS Prepocessors. Warum? Gibt viele Gründe, z.B. die Ergänzung von klassischem CSS um Variablen und Funktionen. Da ich aber plane, dazu eine gesonderte Artikelserie zu starten, will ich hier nicht zuviel verraten. Ich werde aber notwendigerweise auf die hier angesprochen Probleme eingehen.

Wir können bis jetzt tatsächlich einen Erfolg auf unserem Weg ins Semantik-Paradies verbuchen: wir sind unsemantische Klassennamen losgeworden. Gut. Doch wir haben uns neue Probleme ins Haus geholt: unnötige Wiederholungen. Und da kommen Preprocessors wie SASS und LESS ins Spiel.

Mixins: Funktionen mit Klassen-Charakter

Aus den sich wiederholenden Styles machen wir eine Art Funktion. Bei den Preprocessors nennt sich sowas Mixin. Statt float:left schreiben wir sowas wie floatLeft(). Besonders nützlich wird sowas bei Eigenschaften, vor denen momentan noch ein ganzer Haufen Prefix-Rubbish gehört wie z.B. box-shadow. Wie gesagt, dazu mehr in der kommenden Artikelserie.

Was erreichen wir durch das Verwenden von Mixins? Wir fügen statt den eigentlichen Styles lediglich eine Referenz ein. Wenn wir an der Referenz etwas ändern (weil wir z.B. beschließen, dass alle links floatenden Elemente einen bisschen Platz nach rechts via margin-right bekommen sollen), ändern sich auch alle Elemente, die diese Referenz beinhalten.

Klingt vielleicht kompliziert, ist es aber nicht. Vielleicht habe ich es kompliziert ausgedrückt, denn schlussendlich ist es genau wie bei den Klassen. Der Klassenname war die Referenz, nur mit dem Unterschied, dass die Referenz im HTML-Code über class=“left” an ein Element gebunden wird. Bei den Preprocessors setzen wir diese Referenz in der LESS– bzw. Sass-Datei selbst, nicht im HTML. Unser HTML bleibt sauber, d.h. beinhaltet nur – und ich meine wirklich nur – strukturelle Angaben. Ziel erreicht!

Außerdem erreichen wir mithilfe von Mixins eine Modularisierung ähnlich den Prinzipien von OOCSS. Mixins statt Klassen halt. Yay!

Ein Nachteil bleibt: erhöhtes Datenaufkommen durch Wiederholungen

Wer sich bereits ein bissl mit CSS Preprocessors beschäftigt hat, stellt vielleicht fest, dass das anfangs angesprochen erhöhte Datenaufkommen immer noch besteht. Zwar ist dank der Mixins in der Entwicklung die Wartbarkeit gegeben, jedoch beinhaltet das vom Preprocessor generierte CSS nun Wiederholungen. Jedes Mal, wenn ein Mixin aufgerufen wird, wird ja derselbe Output generiert. Wenn ein Mixin also mehrfach verwendet wird – was seiner Natur entspricht – wird mehrfach identischer Output generiert.

Hier stelle ich mich jedoch kackfrech in die Mitte und behaupte mal: das ist nicht so wild. w00t?!?

Ja, denn:

  1. Wir können CSS-Dateien automatisiert beim Speichern minifyen und somit wieder gehörig Datenvolumen gut machen.
  2. Wir sparen auch dadurch wertvolle Bytes, dass wir unser HTML nicht mit Klassennamen zukleistern.
  3. CSS-Dateien werden einmalig übertragen und dann gecached.

Nun ergibt sich aus meinen Ausführungen jedoch möglicherweise auf eurer Seite eine Frage:

Ist OOCSS also Grütze?

Nein. Wenn eine Entwicklung im Smashing Mag vorgestellt wird, darf man davon ausgehen, dass ein gewisser Grad an Relevanz vorhanden ist. OOCSS beinhaltet brauchbare Prinzipien, die sich mit denen eines CSS Preprocessors nicht beißen. Beispiel? Die modularisierte Arbeitsweise für spätere Wiederverwendung gängiger CSS-Styles.

Durch OOCSS haut man sich jedoch das HTML-Dokument mit unnötigen CSS-Klassen voll. Einige davon werden notwendigerweise auch unsemantisch sein. Und hier legt der – Achtung: wertend – Fehler.

Wir sind vielleicht daran gewöhnt, HTML-Elemente mit Klassen zuzupflastern. Eigentlich ist das jedoch Bad Practice. HTML stellt die Struktur, die Gestaltung erfolgt über CSS. So will es das Gesetz 😉

Durch die Verwendung von Preprocessors kann man Klassen im File selbst handlen. Klingt komisch – is aber so. Ich lege einen Mixin namens whiteBox() an und kann diesen dann an den Positionen aufrufen wo es nötig ist. Das funktioniert im klassischen CSS nicht.

Fazit dieses Abschnitts: CSS Preprocessors sind vorzuziehen. Wenn Umstände dies jedoch verbieten (z.B. Arbeiten in einem 8-Mann-Team, das keinen Bock auf LESS oder Sass hat), sind die Prinzipien von OOCSS durchaus einen Blick wert. Dabei sollte man allerdings nicht vergessen, dass hier Konsequenz wichtig ist. Sprecht mit euren Mitarbeitern und überzeugt sie von dieser Herangehensweise. Es müssen alle mitziehen, sonst hat/macht/ergibt es keinen Sinn.

Zusammenfassung (tl;dr)

Hier 3 Regeln, die ich gern zur Diskussion stelle, die aber meine Beachtung bei zukünftigen Entwicklungen finden werden:

  1. Verwendung semantischer Klassennamen zur bestmöglichen Trennung von Struktur und Gestalt
  2. unsemantische bzw. dekorative Klassennamen ersetzen durch ortsabhängige Styles (zur Not an mehreren Stellen definieren)
  3. Preprocessors sind dein Freund

Disclaimer: die Regeln gelten nur in Verbindung mit CSS Preprocessors. Falls diese Möglichkeit nicht besteht, siehe Abschnitt Ist OOCSS also Grütze?.

Autor: Enno

Ich bin Enno. PHP ist mein Ding, aber auch alles Neue rund um die Themen HTML5, CSS3 & Co finde ich interessant. Ich mag es Leuten zu helfen und mein Wissen weiterzugeben. Sollte dir mein Beitrag gefallen haben, lass doch nen Kommentar da oder benutze einen der Social Buttons, um deinen Dank auszudrücken ;)