Große CSS Projekte mit ITCSS strukturieren

Große CSS-Projekte mit ITCSS strukturieren

Je größer das CSS-Projekt wird, desto wichtiger ist es, eine skalierbare und vor allem übersichtliche Struktur zu schaffen. Da es im CSS-Umfeld viele unterschiedliche Herangehensweisen an dieses Problem gibt, möchten wir uns in diesem Artikel mit ITCSS von Harry Roberts beschäftigen.

Was ist ITCSS?

ITCSS ist ein skalierbares Meta-Framework für CSS, welches erstmals von Harry Roberts vorgestellt wurde. Dabei steht ITCSS für „Inverted Triangle CSS“, als „umgekehrtes Dreieck CSS“ und bezieht sich auf die Sortierung der CSS-Anweisungen aufsteigend nach der CSS Specificity. Die Specificity ist die Wertigkeit einer CSS-Anweisung und wird berechnet, indem man die Wertigkeiten aller Selektoren einer Anweisung addiert. Als Beispiel hat die Anweisung body #content .data img:hover eine Specificity von 122: #content 100 + .data 10 + :hover 10 + body 1 + img 1. Dabei haben die einzelnen Selektoren die folgenden Wertigkeiten:

  1. Universal-Selektor *: 0
  2. HTML-Elemente und Pseudo-Elemente: 1
  3. Klassen, Pseudo-Klassen und Attribute: 10
  4. IDs: 100
  5. Inline-Styles: 1000
  6. !important hat eine „unendliche“ Specificity

Die zwei klassischen Wege, CSS zu strukturieren, sind entweder die Spiegelung der Webseiten-Struktur (Styles für den Header, dann Content, dann Footer) oder die thematische Gruppierung (alle Formular-Styles, alle Medien-Styles, Blogposts usw.). Dabei tritt aber das Problem der Specificity auf: der Browser muss zur Darstellung ständig hin und her springen, um die korrekte Kaskade der Styles anwenden zu können. Der dabei entstehende Specificity Graph sieht in etwa so aus:

Klassischer Specificity Graph

Um den dadurch entstehenden Überfluss und die Redundanzen zu minimieren sortieren wir unsere Styles grob nach der Specificity, um einen deutlich saubereren Specificity Graph zu erhalten. „Grob sortieren“ heißt in diesem Fall, dass wir versuchen einen stetig ansteigenden Graphen beizubehalten, minimale Schwankungen können wir tolerieren. Das heißt, dass wir (in einer idealen Welt) zuerst alle HTML-Elemente, danach alle Klassen und zuletzt alle IDs und Anweisungen mit einem !important untereinander anordnen. Die Styles werden also von allgemein nach spezifisch, von weitreichend nach lokal sortiert.

Unser Graph sollte nun in etwa diese Form haben:

ITCSS Specificity Graph

Mit ITCSS sortieren wir unsere Styles nach aufsteigender Specificity, um so ein aufgeräumtes, nicht redundantes CSS zu erhalten.

Technische Struktur mit ITCSS und Grunt

Nachdem die Funktionsweise von ITCSS nun erklärt ist, geht es an die technische Umsetzung. Mit Hilfe von LESS und Grunt lässt sich eine technisch saubere und übersichtliche Lösung umsetzen, die wir hier vorstellen wollen.

ITCSS Verzeichnis-Struktur

Wie im Screenshot zu sehen ist, haben wir in unserem Beispiel die einzelnen ITCSS-Schichten als Verzeichnisse im Template-Verzeichnis angelegt. In dieser Struktur können wir nun für eine bessere Übersicht einzelne Dateien für verschiedene Aufgaben anlegen. Im Screenshot zu sehen ist zum Beispiel eine Style-Datei für Medien, eine für Formulare und eine für Typografie. Die Überlegung dahinter ist, das alle Dateien in einem Verzeichnis grundlegend immer dieselbe Specificity haben. Als Best Practice bietet sich an, jeweils alle Dateien eines Verzeichnisses in einer _all.less Datei zusammen zu fassen und diese Sammeldateien dann in der theme.less wiederum zu sammeln. Eine beispielhafte Struktur nach ITCSS wäre diese:

  1. Settings: LESS- bzw. SASS-Variablen. Sinnvoll wäre hier eine Aufteilung zum Beispiel eine Datei für Farben, Schriften, Grid-Maße und so weiter.
  2. Tools: Mixins aller Art. Hier können zum Beispiel Clearfixes gespeichert werden oder auch Styles, die auf mehrere andere Elemente angewendet werden können. Hinweis: bis zu dieser Ebene wird noch kein CSS erzeugt!
  3. Generic: hier stehen grundlegende Styles wie ein normalize.css, Resets oder box-sizing. Ab dieser Schicht wird tatsächlich CSS erzeugt.
  4. Base: einfache HTML-Elemente. Hier bieten sich einzelne Dateien für zum Beispiel Formulare, Medien (Bilder, Videos), Typografie oder Tabellen an.
  5. Objects: klassenbasierte, nicht-designrelevante Styles wie ein Grid-System finden hier Platz.
  6. Components: klassenbasierte, designrelevante Styles. Hier finden Sie Menus, Widgets oder andere designspezifische Formatierungen.
  7. Trumps: nein, dieser Layer hat nichts mit dem amerikanischen Präsidenten zu tun. Nennen Sie ihn alternativ Overwrites oder Peaks: hier sammeln Sie alle IDs, Überschreibungen für verwendete Libraries oder Anweisungen, die !important verwenden.

Nachdem wir so unsere Dateien strukturiert haben geht es nun an die Weiterverarbeitung mittels Grunt. Hierzu werden mehrere Grunt-Tasks benötigt: clean bereinigt unsere früheren kompilierten Dateien, concat fasst mehrere Dateien zusammen, less kompiliert unsere LESS-Dateien in CSS und cssmin minimiert das fertige CSS. Da wir uns an die ITCSS-Struktur gehalten haben sollte unser CSS nun einen entsprechend aufgeräumten Specificity Graphen haben.

Allgemeine Hinweise zur Verwendung von Libraries

Libraries wie Twitter Bootstrap oder Zurb Foundation haben mittlerweile ihren festen Platz in der Webentwicklung gefunden. Allerdings bleibt zu bedenken, welche Komponenten man tatsächlich benötigt und ob es sich im Endeffekt lohnt, die komplette Library einzubinden. Aus unserer Erfahrung heraus ist das meist nicht der Fall. Da es in den meisten Fällen auch LESS- bzw. SASS-Versionen der Libraries gibt sollte man versuchen, diese Versionen direkt an der richtigen Stelle im ITCSS-Baum einzubinden.

Am optimalsten ist es natürlich, wenn man anstatt der fertigen Styles Mixins benutzt, sofern die verwendete Library welche zur Verfügung stellt. Zurb Foundation zum Beispiel bietet für viele seiner Komponenten Mixins an, so dass man diese im Tools-Layer einbinden und dann in der jeweiligen Schicht (meist Objects oder Components) in den eigenen Styles verwendet.

Ein Wort zu Media Queries

Da Media Queries ja bereits vorhandene CSS-Anweisungen überschreiben ist es eine gute Vorgehensweise, diese an das Ende einer jeden CSS-Datei zu stellen. Ob dabei mit Progressive Enhancement und min-width gearbeitet wird oder mit Graceful Degradation und max-width ist dabei erstmal unerheblich (wobei natürlich unsere Empfehlung Progressive Enhancement wäre). Aber wie kann man nun die Media Queries, die ja unter normalen Umständen im ganzen LESS-Quellcode verstreut sind, sauber in ITCSS integrieren?

Mit Hilfe des Grunt-Tasks mqe (Media Query Extractor) können wir uns aus unserem fertigen CSS alle vorkommenden Media Queries in eigene Dateien extrahieren. So erhalten wir zum Beispiel eine Datei für den 768px-Breakpoint, den 992px-Breakpoint und so weiter. Diese zusätzlichen Dateien können wir nun wieder über den Grunt-Task concat in der von uns gewünschten Reihenfolge zusammenbauen (mit den Media Queries am Schluß) und erhalten so eine CSS-Datei, in der zuerst alle normalen Styles der Specificity nach geordnet sind und dann alle Media Queries aufsteigend und ebenfalls ITCSS-konform sortiert aufgeführt sind. Zuletzt kann alles wie gewohnt minimiert und eingebunden werden.

Nachdem unsere Dateien in ITCSS-konformen Verzeichnissen strukturiert worden sind, können wir diese mittels Grunt optimieren: alle Dateien werden zusammengefasst und kompiliert, Media Queries werden aus dem resultierenden CSS extrahiert und schlußendlich zu einer finalen CSS-Datei zusammengeführt und minimiert.

Fazit

Um performante und klar strukturierte Stylesheets zu erzeugen ist ITCSS ein mächtiges Werkzeug. Man kann ITCSS ohne Probleme mit anderen Methodiken wie BEM verwenden und ist dabei beliebig skalierbar. Im Zusammenspiel mit weiteren Techniken wie Progressive Enhancement oder Optimierungen wie Critical CSS ist man so in der Lage, schnell performante und vor allem wartbare Stylesheets für den eigenen Online-Shop oder die Webseite zu erzeugen.

Quellen: