@@1unitedpower
Der CSS-in-JS Community geht es nicht darum ein neues Paradigma zu beschwören, sondern Lösungen für diverse Probleme von CSS zu finden
Ich habe eher den Eindruck, sie sehen oftmals als Probleme an, was sie nicht verstehen: Kaskade, Spezifität, Andersartigkeit von CSS gegenüber JavaScript. Was aber gar keine Probleme sind, die „gelöst“ werden müssten. Genau das nimmt Heydon aufs Korn.
Ich versuch mal anhand von styled-components zu erklären, wo die Vor- und Nachteile von CSS-in-JS liegen. Dazu hol ich mal etwas weiter aus, auch in dem Wissen, dass nicht jeder Leser schon mal von CSS-in-JS gehört haben wird. Zu HTML4-Zeiten war HTML noch eine Suppe aus semantischen und präsentations-bezogenen Elementen:
⸾ ⸾ ⸾ ⸾
┌───────┐
│ Suppe │
└───────┘
Spätestens mit HTML5 hat sich eine klare Trennung der Zuständigkeiten durchgesetzt: HTML dient der semantischen Auszeichnung der Dokumentstruktur und CSS der Präsentation:
┌───────┐
│ HTML │
├───────┤
│ CSS │
└───────┘
Seit einigen Jahren hat sich zu dieser vertikalen Trennung der Zuständigkeiten auch eine horizontale Trennung gesinnt. Wiederverwendbare UI-Widgets, wie Navigationen oder Map-Views, werden als unabhängige, in-sich-abgeschlossene Komponenten entwickelt. Das macht aus Software-Engineering-Perspektive Sinn, weil der Verwender des Map-Views nicht die Implementations-Details kennen muss, sondern nur die öffentliche Schnittstelle.
┌──────────────────┬──────────────┐
│ Navigation HTML │ MapView HTML │
├──────────────────┴──────────────┤
│ CSS │
└─────────────────────────────────┘
styled-components spinnen diese Idee weiter, und erlauben die horizontale Trennung auch dem CSS-Layer fortzusetzen:
┌──────────────────┬──────────────┐
│ Navigation HTML │ MapView HTML │
├──────────────────┼──────────────┤
│ Navigation CSS │ MapView CSS │
├──────────────────┴──────────────┤
│ Globales Theme CSS │
└─────────────────────────────────┘
Der Hintergrund-Gedanke ist ein ähnlicher: Der Verwender einer stilisierten Komponente, sollte sich nicht mit den Implementations-Details rumschlagen, sondern nur mit einer definierten CSS-Schnittstelle. Die Schnittstelle bildet ein sogenannter ThemeProvider, das ist eine globale Sammlung von CSS-Regeln, die von allen Komponenten geteilt werden.
Das hat ein paar Nachteile:
- Es ist ein Build-Schritt erforderlich, der zur Compile-Zeit die CSS-in-JS-Angaben ausliest und daraus eine CSS-Datei baut.
- Es gibt einen zusätzlichen Indirektions-Schritt zwischen hartkodierten Styles und dem Theme-Provider.
- Man muss mehr Arbeit in die Planung von Komponenten investieren, um sie hinreichend flexibel zu gestalten, sodass sie sicht nahtlos in beliebige Themes integrieren.
- Ist man selber nicht der Autor einer Komponente, sondern nur der Nutzer, ist es aufwendiger die Implementierung zu ändern.
Aber auch ein paar Vorteile
- Der Stil einer Komponente beeeinflusst niemals den Stil einer anderen Komponente.
- Es befürwortet Konsistenz: Eine Komponente kann beliebig oft instantiiert werden und hat immer den selben Look&Feel (modulo unterschiedlicher Themes).
- Zwischen den Komponenten wird Konsistenz über ein globales Theme geflegt. Das ermöglicht Änderungen, die das ganze System betreffen, an einer einzigen Stelle zu pflegen. Wie schon gesagt, kann das auch zum Nachteil werden, wenn eine Komponente nicht hinreichend flexibel ist und dafür geändert werden müsste.
- Es ist möglich nur kritisches CSS auszuliefern, und das CSS von unbenutzten Komponenten zu verbergen. Und CSS-Dateien werden minifiziert.
- CSS-Regelsätze sind an Komponenten gebunden, der Compiler ist so klug automatisch ein Stylesheet daraus zu generieren. Das empfinde ich als besonders angenehm gegenüber herkömmlichen CSS, das Mapping von CSS-Regelsätzen auf den DOM-Tree wird mir komplett abgenommen.
- Man kann beliebige JavaScript-Funktionen benutzen, um bswp. Farben zu manipulieren.
- Man vermeidet toten CSS-Code und CSS-Wucher
- Es ist vergleichsweise einfach komplexe Transitionen zu choreografieren.