Dieses Dokument enthält eine eingehende Analyse aller aktuellen CSS-in-JS- Lösungen, die die Server-Seite-Rendering und das TypeScript unterstützen.
Die Basisreferenz, die wir zum Vergleich verwenden werden, ist ein CSS -Moduleansatz .
Wir verwenden Next.js als SSR -Framework für den Aufbau von Ressourcen.
Der letzte wichtige Aspekt ist die Typ-Sicherheit mit vollem Typuskriptunterstützung .
? Letztes Update: August 2021
? Um einen kürzeren Überblick zu erhalten, können Sie den Artikel über CSS -Tricks auschecken:
https://css-tricks.com/a-thorough-analysis-of-css-in-js/
? Wenn Sie stattdessen ein Video bevorzugen, können Sie meinen Vortrag von ngpartycz überprüfen:
https://www.youtube.com/watch?v=c7uwghrax9a
Bitte überprüfen Sie unsere Ziele und Haftungsausschluss, bevor Sie zu Schlussfolgerungen springen.
Die CSS-Sprache und die CSS-Module haben einige Einschränkungen, insbesondere wenn wir einen Typ-Safe-Code haben möchten. Einige dieser Einschränkungen haben alternative Lösungen, andere sind nur ärgerlich oder weniger als ideal :
Stile können nicht mit Komponenten zusammengeführt werden
Dies kann frustrierend sein, wenn viele kleine Komponenten erfasst, aber es ist kein Deal Breaker. Die Erfahrung, zwischen der Datei component.js und der Datei component.css , die nach einem bestimmten Klassennamen zu suchen und nicht einfach in die Stildefinition zu gehen , eine wichtige Produktivitätsnachteils ist.
Das Styling Pseudos und Medienfragen erfordert die Duplikation für die Auswahl
Eine weitere frustrierende Tatsache ist die Notwendigkeit, unsere CSS -Klassen bei der Definition von Pseudoklassen und Elementen oder Medienfragen zu duplizieren. Wir können diese Einschränkungen mit einem CSS -Präprozessor wie Sass, Less oder Stylus überwinden, der den & übergeordneten Selektor unterstützt und das kontextbezogene Styling ermöglicht.
. button {}
/* duplicated selector declaration for pseudo classes/elements */
. button : hover {}
. button :: after {}
@media ( min-width : 640 px ) {
/* duplicated selector declaration inside media queries */
. button {}
} Die Verwendung der Stile wird von ihrer Definition getrennt
Wir erhalten keine Intellisense mit CSS-Modulen, über die CSS-Klassen in der Datei component.css definiert sind, wodurch Kopienpaste zu einem erforderlichen Tool gemacht werden, wodurch der DX gesenkt wird. Aufgrund der mangelnden Sicherheit macht es auch sehr umständlich .
Die Verwendung von Typ-Safe-Design-Token in CSS ist nicht trivial
In JS/TS definiert (um von Typ-Safety zu profitieren) können in CSS nicht direkt verwendet werden.
Es gibt mindestens 2 Problemumgehungen für dieses Problem, von denen keiner elegant ist:
.module.css verwenden..css Datei.Mit dieser Analyse suchen wir bestimmte Ziele:
Wenn wir noch spezifischer werden, wollten wir die Verwendung verschiedener CSS-in-JS-Lösungen in Bezug auf:
props (auch bekannt als Komponentenvarianten) oder von BenutzereingabenDiese Analyse soll objektiv und nicht optimiert sein:
? Was werden Sie hier nicht finden?
? Was wirst du hier finden?
Die Bibliotheken werden in keiner bestimmten Reihenfolge dargestellt. Wenn Sie an einer kurzen Geschichte von CSS-in-JS interessiert sind, sollten Sie die Vergangenheit, Gegenwart und Zukunft von CSS-in-JS-aufschlussreichem Gespräch von Max Stoiber überprüfen.
| 1. Co -Location | 2. DX | 3. tag` ` | 4. { } | 5. ts | 6. & ctx | 7. Nist | 8. Thema | 9. .css | 10. <style> | 11. Atomic | 12. className | 13. <Styled /> | 14. css Prop | 15. Agnostisch | 16. Seitengröße Delta | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CSS -Module | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | - - | |||||||||
| Gestylt JSX | ✅ | ? | ✅ | ? | ✅ | ✅ | ✅ | +2.8 kB / +12.0 kB | ||||||||
| Gestaltete Komponenten | ✅ | ? | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +13.4 kB / +39.0 kB | ||||
| Emotion | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +6.5 kB / +20.0 kB | ||
| Typil | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ? | ✅ | ✅ | ✅ | +2.1 kB / +8.0 kB | |||||
| Fela | ✅ | ? | ? | ✅ | ? | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +11.9 kB / +43.0 kB | |||
| Stiche | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ? | ✅ | +5.3 kB / +17.0 kB | |||
| JSS | ✅ | ✅ | ? | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ? | ✅ | +18.2 kB / +60.0 kB | |||
| Goober | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ? | ✅ | +1.1 kB / +4.0 kB | ||
| Zusammengestellt | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ? | ✅ | ✅ | +3.5 kB / +9.0 kB | |||
| Linaria | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +2.7 kB / +6.0 kB | ||||
| Vanilla-Extract | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ? | ✅ | ✅ | +0.0 kB / -2.0 kB |
Die Fähigkeit, Stile in derselben Datei wie die Komponente zu definieren. Beachten Sie, dass wir die Stile auch in eine separate Datei extrahieren und importieren können, falls wir sie bevorzugen.
⬆️ Übersicht
Bezieht sich auf die Entwicklererfahrung , die 2 Hauptaspekte umfasst:
⬆️ Übersicht
tag` ` (Tagged Vorlagen)Unterstützung für die Definition von Stilen als Zeichenfolgen mit ES -Tagged -Vorlagen:
kebab-case für Eigenschaftsnamen genau wie die einfache CSS-Syntax;string aussehen.⬆️ Übersicht
{ } (Objektstile)Unterstützung für die Definition von Stilen als Objekte unter Verwendung von einfachen JavaScript -Objekten:
camelCase für Eigenschaftsnamen, wie wir es in React Native tun würden.⬆️ Übersicht
Die Support von TypeScript, entweder integriert oder über @types -Paket, das umfasst:
Props Generics, gegebenenfalls zutreffend (type-sicherer Zugriff auf Komponenten-Requisiten-Typen erhalten, wenn dynamische Stile definiert werden);⬆️ Übersicht
& ctx (Kontextstile)Unterstützung für kontextbezogene Stile, mit denen wir Pseudo -Klassen & -Elemente und Medienabfragen leicht definieren können, ohne den Selektor zu wiederholen, wie in CSS erforderlich:
& Parent Selector unterstützen;⬆️ Übersicht
Unterstützung für willkürliche verschachtelte Selektoren :
⬆️ Übersicht
Integrierte Unterstützung für Themen oder Verwaltung von Token für ein Designsystem.
Wir haben diese Funktion nicht getestet , daher machen wir nur Notizen, welche Bibliotheken ihre Unterstützung in ihren Dokumenten ausdrücken.
⬆️ Übersicht
.css (statische CSS -Extraktion) Definierte Stile werden als statische .css -Dateien extrahiert:
⬆️ Übersicht
<style> Tag Definierte Stile werden in <style> -Tags im Dokument <head> injiziert:
⬆️ Übersicht
Die Fähigkeit, Atom -CSS -Klassen zu erzeugen, wodurch die Wiederverwendbarkeit des Stils erhöht und die Duplikation verringert wird:
⬆️ Übersicht
className Die Bibliotheks -API gibt eine string zurück, die wir zu unserer Komponente oder unserem Element hinzufügen müssen.
⬆️ Übersicht
<Styled /> Die API erstellt eine Wrapper- (oder Styled ) Komponente, die die generierten className (en) enthält:
StyledButton oder StyledList anstelle von Konstanten wie button_styles oder list_styles . In Bezug auf die Benennung ist es also so ziemlich dasselbe.⬆️ Übersicht
css Prop Ermöglicht das Übergeben von Stilen mit einer speziellen css -Requisite, ähnlich wie wir Inline -Stile definieren, aber die Bibliothek generiert einen einzigartigen CSS -Klassennamen hinter den Kulissen:
⬆️ Übersicht
Ermöglicht die Verwendung ohne oder mit einem Rahmen. Einige Bibliotheken werden speziell nur für React erstellt.
Hinweis : Einige Bibliotheken wie Stiche oder Emotionsdokument reagieren nur die Verwendung, obwohl sie einen Kern haben, der agnostisch ist.
⬆️ Übersicht
Die Differenz der Gesamtseite der Seitengrößen in KB (übertragene GZIPED & Minified / Unkomprimed & Minified) im Vergleich zu CSS -Modulen für den gesamten Index -Seitenproduktionsergebnis unter Verwendung von Next.js:
HINWEIS: Alle Builds wurden mit dem 11.1.0 durchgeführt.
⬆️ Übersicht
Die folgenden Beobachtungen gelten für alle Lösungen (mit geringfügigen spitzen Ausnahmen).
Die nur in einer bestimmten Route verwendeten Komponenten werden nur für diese Route gebündelt. Dies ist etwas, was als nächstes.js außerhalb des Boxs ausführt.
Alle Lösungen bieten eine Möglichkeit, globale Stile zu definieren, einige mit einer dedizierten API.
Alle Lösungen bieten serverseitige Rendering-Unterstützung und sind einfach zu integrieren.
Alle Lösungen fügen automatisch Anbieter-spezifische Präfixe aus dem Feld hinzu.
Alle Lösungen generieren eindeutige Klassennamen, wie es CSS -Module tun. Der zur Generierung dieser Namen verwendete Algorithmus variiert sehr zwischen Bibliotheken:
.heading -Stil von Card wird immer die .Card_heading_h7Ys5 Hash enthält)..heading-0-2-1 , .input-0-2-2 ) oder die Alphabet-Buchstaben ( a, b, c, ... aa, ab, ac usw.), was diesen Ansatz mehr leistungsfähiger macht, aber zu nicht genehmigten Klassennamen (nicht herausfinden kann, ob dies potenzielle Nachteile oder nicht nicht); Keine der Lösungen erzeugt Inline -Stile, was ein älterer Ansatz ist, der von Radium & Glamour verwendet wird. Der Ansatz ist weniger leistungsfähig als CSS -Klassen und wird nicht als Hauptmethode zur Definition von Stilen empfohlen. Es bedeutet auch, dass JS -Event -Handler verwendet werden, um Pseudoklassen auszulösen, da Inline -Stile sie nicht unterstützen. Anscheinend haben sich heutzutage alle modernen Lösungen von diesem Ansatz entfernen.
Alle Lösungen unterstützen die meisten CSS -Eigenschaften, die Sie benötigen: Pseudo -Klassen & -Elemente , Medienabfragen und Keyframes sind diejenigen, die wir getestet haben.
Die meisten Lösungen vermarkten sich während der SSR als "kritische CSS" . Bitte beachten Sie, dass sich dies nicht auf die oberfache kritische CSS-Extraktion bezieht , wie wir ursprünglich dachten.
Was sie tatsächlich tun:
Bei 100% statischer CSS würde es tatsächlich keinen Nutzen geben. Bei dynamischen Seiten, die nur sehr wenige Elemente auf dem Server rendern, und die meisten Komponenten auf dem Client dynamisch gerendert werden, nimmt der Nutzen zu.
Ausnahme : Bibliotheken, die die statische CSS -Extraktion verwenden.
Das Verständnis, wie sich diese Funktionen auf Kern -Web -Vitale und Leistungsmetriken im Allgemeinen auswirken, ist ein äußerst wichtiger Faktor, der den Kunden zu berücksichtigen ist, und die Art und Weise, wie Stile dem Kunden geliefert werden, hat wahrscheinlich den größten Einfluss. Analysieren wir dies also im Detail.
Außerdem müssen wir zwei verschiedene Szenarien berücksichtigen:
.js , .css , Medien usw.). .css -Dateiextraktion Lösungen, die .css statische Dateien generieren, die Sie normalerweise als <link> -Tag (en) in der <head> Ihrer Seite aufnehmen würden, sind im Grunde genommen Rendering-Blocking-Ressourcen. Dies wirkt sich stark auf FCP , LCP und alle anderen Metrik aus.
? Leerer Cache
Wenn der Benutzer einen leeren Cache hat, muss Folgendes auftreten, was sich negativ auf FCP und LCP auswirkt:
<body> , auch wenn der gesamte HTML bereits geladen ist und es möglicherweise sogar eifrig analysiert wird und einige bereits im Voraus abgerufene Ressourcen; Es ist wahr, dass Sie parallel andere <head> -Ressourcen (zusätzliche .css oder .js -Dateien) holen können, aber dies ist im Allgemeinen eine schlechte Praxis.
? Voller Cache
Bei nachfolgenden Besuchen würde jedoch die gesamte .css -Ressource zwischengespeichert, sodass FCP und LCP positiv beeinflusst werden.
Schlüsselpunkte
Diese Lösung scheint besser geeignet zu sein, wenn:
.css -Datei, die beim Besuch anderer Seiten zwischengespeichert werden kann.<style> Tag injizierte Stile Während der SSR werden Stile im <style> -Tag (n) in der <head> der Seite hinzugefügt. Beachten Sie, dass diese normalerweise nicht alle für die Seite benötigten Stile enthalten, da die meisten Bibliotheken eine kritische CSS -Extraktion ausführen, sodass diese styles normalerweise kleiner sein sollten als die gesamte .css -statische Datei, die zuvor diskutiert wurde.
? Leerer Cache
Da wir weniger CSS -Bytes versenden und in der .html -Datei eingebaut sind, würde dies zu einem schnelleren FCP und LCP führen:
.css -Dateien, sodass der Browser nicht blockiert ist..js -Dateienanfragen an das Ende des Dokuments verschieben, wird <head> keine Anfragen ausführen, sodass das Rendering superschnell auftritt..css -Extraktion nicht benötigt wurden:.js -Dateien zusammen mit den Komponenten während der Flüssigkeitszufuhr gebündelt sind (dies schließt alle kritischen CSS ein, die bereits in das <style> Tag + andere versendet werden); ? Voller Cache
Wenn der Cache des Benutzers voll ist, müssen die zusätzlichen .js -Dateien nicht abrufen, da diese bereits zwischengespeichert werden.
Wenn die Seite jedoch SSRED ist, wird das im <style> Tag des Dokuments verwendete kritische CSS erneut heruntergeladen, es sei denn, wir beschäftigen uns auch mit statischer HTML, die auch zwischengespeichert werden können, oder wir befassen uns mit HTML -Caching auf unserer Infrastruktur.
Standardmäßig werden wir auf jeder Seite HTTP -Anfrage zusätzliche Bytes versenden, unabhängig davon, ob sie zwischengespeichert werden oder nicht.
Schlüsselpunkte
Diese Lösung scheint besser geeignet zu sein, wenn:
Die meisten Lösungen besagen, dass sie ungenutzte Code/Stile entfernen . Dies ist nur ein halbes Jahr .
Der nicht verwendete Code ist in der Tat schwieriger zu sammeln, insbesondere wenn Sie ihn mit einfachen .css -Dateien vergleichen, wie wir vor einem Jahrzehnt geschrieben haben. Im Vergleich zu CSS -Modulen sind die Unterschiede jedoch nicht so groß. Jede Lösung, die die Möglichkeit bietet, willkürliche Selektoren oder verschachtelte Stile zu definieren, wird sie bündeln, unabhängig davon, ob sie in unserer Komponente verwendet werden oder nicht. Wir haben es geschafft, nicht verwendete SSR -Stile mit allen getesteten Lösungen zu versenden.
True & vollständige ungenutzte Codeentfernung ist schwer zu implementieren, da die CSS-Syntax weder vom Typ überprüft noch statisch analyzbar ist. Auch die dynamische Natur von Komponenten macht es in bestimmten Szenarien praktisch unmöglich, insbesondere wenn das Markup dynamisch gerendert wird:
& span : Nachkommenelemente;&:nth-child() : Bestimmte Pseudo-Selektoren;& .bg-${color} : Dynamische Selektoren;.parent & : Elternauswahl;Grundsätzlich erhalten wir die Codeentfernung, wenn wir die Komponente löschen oder sie nicht mehr importieren. Das ist implizite Verhalten, da die Stile eine direkte Abhängigkeit der Komponente sind. Wenn die Komponente weg ist, sind es auch ihre Stile.
Es gibt 2 Methoden, um CSS in das DOM zu injizieren und es aus JavaScript zu aktualisieren:
<style> Tag (en) Dieser Ansatz <style> das Hinzufügen eines oder mehrere <style> -Tags (n) im DOM (entweder im <head> oder irgendwo in <style> <body> ).
<style> -Tag und die Aktualisierung des gesamten Inhalts verwenden, können Sie das gesamte DOM langsam aktualisieren, wenn wir nur einen winzigen Satz von CSS -Regel (en) geändert haben.DEVELOPMENT , da sie ein besseres Debugging -Erlebnis bietet.PRODUCTION . CSSStyleSheet -API Diese Methode wird zunächst von JSS verwendet und verwendet CSSStyleSheet.insertRule() , um CSS -Regeln direkt in das CSSOM zu injizieren.
<style> -Tag.<style> -Tag aus auswählen.$0 in Chrome Devtools Zugriff (oder beziehen Sie sich auf andere Weise mit der DOM -API darauf)..sheet.cssRules auf dem <style> -Tag, um das Array der CSS -Regeln zu sehen, die es enthält.PRODUCTION verwenden.DEVELOPMENT . Wenn dieselbe Komponente von 2 verschiedenen Routen importiert wird, wird sie zweimal an den Client gesendet. Dies ist sicherlich eine Einschränkung des Bundler-/Build-Systems, in unserem Fall Next.js und nicht mit der CSS-in-JS-Lösung .
In Next.js funktioniert die Codespaltung auf der Routenebene und bündelt alle für eine bestimmten Route erforderlichen Komponenten aus. Laut ihrem offiziellen Blog und ihrem Web.dev sollte es jedoch in mehr als 50% der Seiten verwendet werden, sollte sie in das commons Bündel aufgenommen werden. In unserem Beispiel haben wir jedoch 2 Seiten, von denen jede die Button importiert und in jedem Seitenbündel enthalten ist, nicht im commons -Bündel. Da der für das Styling erforderliche Code mit der Komponente gebündelt ist, wirkt sich diese Einschränkung auch auf die Stile aus, sodass es sich lohnt, dies zu berücksichtigen.
Dies ist ein gut etablierter, reifer und fester Ansatz. Ohne Zweifel ist es eine große Verbesserung gegenüber BEM, SMACCS, OOCS oder einer anderen skalierbaren CSS-Methodik, um unsere CSS zu strukturieren und zu organisieren, insbesondere in komponentenbasierten Anwendungen.
Ins Leben gerufen im Jahr 2015 | Zurück zur Übersicht
✅ Fertigstellung des Kontext-bewussten Code
✅ Framework Agnostisch
Keine Styles/Komponenten Co-Lokation
KEINE TISTESCIPS -Unterstützung
Keine Atom -CSS
Keine themenbezogene Unterstützung
Styles Definitionsmethode (en)
Styles nisten
Stile anwenden Methoden (en)
classNamestyled Komponentecss -PropStylesausgabe
.css -Dateiextraktion<style> Tag -InjektionDies ist die Grundlinie, die wir beim Vergleich aller folgenden CSS-in-JS- Lösungen in Betracht ziehen werden. Checkout der Motivation, die Grenzen dieses Ansatzes besser zu verstehen, den wir zu füllen versuchen.
| Übertragen / gzipiert | Unkomprimiert | |
|---|---|---|
| Indexseitengröße | 76,7 kb | 233 KB |
Page Size First Load JS
┌ ○ / 2.19 kB 68.7 kB
├ └ css/1d1f8eb014b85b65feee.css 450 B
├ /_app 0 B 66.5 kB
├ ○ /404 194 B 66.7 kB
└ ○ /other 744 B 67.2 kB
└ css/1c8bc5a96764df6b92b4.css 481 B
+ First Load JS shared by all 66.5 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.40892d.js 555 B
├ chunks/webpack.ddd010.js 822 B
└ css/a92bf2d3acbab964f6ac.css 319 B
Eine sehr einfache Lösung, keine dedizierte Website zur Dokumentation, alles ist auf GitHub. Es ist nicht beliebt, aber es ist die eingebaute Lösung in Next.js.
Version: 4.0 | Aufrechterhalten von Vercel | 2017 ins Leben gerufen | Dokumente anzeigen | ... Zurück zur Übersicht
✅ Styles/Komponenten Co-Lokation
? CONTEXT-ANTWORT-CODE-Abschluss : Um eine Syntax-Hervorhebung und -code-Fertigstellung abzurufen, ist eine Editor-Erweiterung erforderlich
? TypeScript -Support : @types kann zusätzlich installiert werden, aber die API ist zu minimal, um TS zu benötigen
Keine Atom -CSS
Keine themenbezogene Unterstützung
Nicht agnostisch rahmen
Styles Definitionsmethode (en)
Styles nisten
Stile anwenden Methoden (en)
classNamestyled Komponentecss -PropStylesausgabe
.css -Dateiextraktion<style> Tag -Injektion elements abzielen, und es generiert eindeutige Klassennamen für sie (nicht sicher, ob es eine gute Praxis ist) Insgesamt hatten wir das Gefühl, einfache CSS zu schreiben, mit dem zusätzlichen Vorteil, dass wir die Stile zusammen mit der Komponente definieren können, sodass wir keine zusätzliche .css -Datei benötigen . In der Tat ist dies die Philosophie der Bibliothek: Unterstützung der CSS -Syntax in der Komponentendatei. Wir können alle JS/TS -Konstanten von Funktionen mit String -Interpolation verwenden . Die Arbeit mit dynamischen Stilen ist ziemlich einfach, da es am Ende einfach JavaScript ist. Wir erhalten all diese Vorteile zu einem sehr niedrigen Preis, mit einem ziemlich kleinen Bündel -Overhead .
Die Nachteile sind die Gesamterfahrung des Schreibens einfacher CSS. Ohne Unterstützung von Pseudoklassen/-elementen und Medienfragen zu unterstützen , werden sie ziemlich umständlich zu verwalten.
| Übertragen / gzipiert | Unkomprimiert | |
|---|---|---|
| Indexseitengröße | 79,5 kb | 245 kb |
| gegen CSS -Module | +2.8 kb | +12 kb |
Page Size First Load JS
┌ ○ / 2.65 kB 72.6 kB
├ /_app 0 B 70 kB
├ ○ /404 194 B 70.2 kB
└ ○ /other 1.18 kB 71.2 kB
+ First Load JS shared by all 70 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.a4b061.js 4.12 kB
└ chunks/webpack.61f1b6.js 778 B
Sicher eine der beliebtesten und reifen Lösungen mit guter Dokumentation. Es verwendet markierte Vorlagen, um Stile standardmäßig zu definieren, kann jedoch auch Objekte verwenden. Außerdem wurde der Ansatz der styled Komponenten populär, wodurch zusammen mit den definierten Stilen eine neue Komponente erstellt wird.
Version: 5.3 | Gepflegt von Max Stoiber & anderen | Start im Jahr 2016 | Dokumente anzeigen | ... Zurück zur Übersicht
✅ Styles/Komponenten Co-Lokation
✅ TypeScript -Support : @types muss zusätzlich installiert sein, über definitiv
✅ Eingebaute Themenunterstützung
✅ Framework Agnostisch
? CONTEXT-ANTWORT-CODE-Abschluss : Benötigt eine Editor-Erweiterung/ein Plugin
Keine Atom -CSS
Styles Definitionsmethode (en)
Styles nisten
Stile anwenden Methoden (en)
classNamestyled Komponentecss PropStylesausgabe
.css -Dateiextraktion<style> Tag -Injektion Props usw.) Styled Components bietet einen neuartigen Ansatz zum Styling -Komponenten mithilfe der styled Methode, die eine neue Komponente einschließlich der definierten Stile erstellt. Wir haben keine Lust, CSS zu schreiben, daher müssen wir aus CSS -Modulen einen neuen, programmatischen Weg lernen, um Stile zu definieren. Da es sowohl string als auch object ermöglicht, ist es eine ziemlich flexibile Lösung, um unsere vorhandenen Stile zu migrieren, und um ein Projekt von Grund auf neu zu starten. Außerdem haben die Betreuer einen ziemlich guten Job gemacht, um mit den meisten Innovationen in diesem Bereich Schritt zu halten.
Vor der Übernahme müssen wir uns jedoch bewusst sein, dass es mit bestimmten Kosten für unsere Bündelgröße einhergeht.
| Übertragen / gzipiert | Unkomprimiert | |
|---|---|---|
| Indexseitengröße | 90,1 kb | 272 kb |
| gegen CSS -Module | +13,4 kb | +39 kb |
Page Size First Load JS
┌ ○ / 2.52 kB 83.1 kB
├ /_app 0 B 80.6 kB
├ ○ /404 194 B 80.8 kB
└ ○ /other 1.06 kB 81.7 kB
+ First Load JS shared by all 80.6 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.731ace.js 14.7 kB
└ chunks/webpack.ddd010.js 822 B
Wahrscheinlich die umfassendste, vollständigste und sogenistische Lösung. Detaillierte Dokumentation, vollständig mit TypeScript erstellt, sieht sehr ausgereift, reich an Funktionen und gut gepflegt aus.
Version: 11.4 | Pflege von Mitchell Hamilton & Andere | 2017 ins Leben gerufen | Dokumente anzeigen | ... Zurück zur Übersicht
✅ Styles/Komponenten Co-Lokation
✅ TypeScript -Unterstützung
✅ Eingebaute Themenunterstützung
✅ CONTEXT-ARTEALE-CODE-Fertigstellung : Für die Verwendung des Ansatzes der styled Komponenten ist ein zusätzliches Editor-Plugin erforderlich
✅ Framework Agnostisch
Keine Atom -CSS
Styles Definitionsmethode (en)
Styles nisten
Stile anwenden Methoden (en)
className (mit @emotion/CSS)styled Komponentecss PropStylesausgabe
.css -Dateiextraktion<style> Tag -Injektion css -Prop bietet eine große Ergonomie während der Entwicklung. Es scheint jedoch ein neuerer Ansatz zu sein, der auf React 17 New jsx -Transformation basiert, und das Konfigurieren ist nicht trivial, unterscheidet sich von Ihrem Setup und impliziert eine Kesselplatte (die sich bald ändern und einfacher werden sollte) styled -Ansätzen fügt unserem Bundle 3 kB hinzu, da es aus einem separaten Paket importiert wirdcss -Requisiten- und styled Komponenten) Die allgemeine Emotionen scheint ein sehr solider und flexibler Ansatz zu sein. Der neuartige css -Prop -Ansatz bietet Entwicklern eine großartige Ergonomie. Die Arbeit mit dynamischen Stilen und Typenkripten ist ziemlich einfach und intuitiv. Bei der Definieren von Stilen und der Unterstützung von strings und objects kann es sowohl bei der Migration von einfachen CSS als auch bei der von vorne anfangen von vorne anfangen. Das Bündel -Overhead ist nicht vernachlässigbar, aber definitiv viel kleiner als andere Lösungen, insbesondere wenn Sie die reichhaltigen Funktionen betrachten, die es bietet.
Es scheint, dass es sich nicht auf die Leistung konzentriert, sondern mehr auf Entwicklererfahrungen. Es sieht aus wie eine perfekte "abgerundete" Lösung.
| Übertragen / gzipiert | Unkomprimiert | |
|---|---|---|
| Indexseitengröße | 83,2 kb | 253 kb |
| gegen CSS -Module | +6,5 kb | +20 kb |
Page Size First Load JS
┌ ○ / 2.5 kB 76.4 kB
├ /_app 0 B 73.9 kB
├ ○ /404 194 B 74.1 kB
└ ○ /other 1.07 kB 74.9 kB
+ First Load JS shared by all 73.9 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.6cb893.js 23.3 kB
├ chunks/pages/_app.b6d380.js 7.68 kB
└ chunks/webpack.ddd010.js 822 B
Minimaler Bibliothek, konzentriert sich nur auf die Typ-Überprüfung. Es ist agnostisch Framework, deshalb hat es keine spezielle API für den Umgang mit dynamischen Stilen. There are React wrappers available, but the typings feels a bit convoluted.
Version: 2.1 | Maintained by Basarat | Launched in 2017 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Framework agnostic
? Built-in Theming support : uses TS namespaces to define theming, which is not a recommended TS feature even by the author himself, or by TS core team member Orta Therox.
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection <style> tag with all the styles, and replaces it on update, and apparently it doesn't use insertRule() , not even in production builds, which might be an important performance drawback in large & highly dynamic UIs Overall TypeStyle seems a minimal library, relatively easy to adopt because we don't have to rewrite our components, thanks to the classic className approach. However we do have to rewrite our styles, because of the Style Object syntax. We didn't feel like writting CSS, so there is a learning curve we need to climb.
With Next.js or React in general we don't get much value out-of-the-box, so we still need to perform a lot of manual work. The external react-typestyle binding doesn't support hooks, it seems to be an abandoned project and the typings are too convoluted to be considered an elegant solution.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 78.8 kB | 241 kB |
| vs. CSS Modules | +2.1 kB | +8 kB |
Page Size First Load JS
┌ ○ / 2.44 kB 72.1 kB
├ /_app 0 B 69.7 kB
├ ○ /404 194 B 69.9 kB
└ ○ /other 975 B 70.7 kB
+ First Load JS shared by all 69.7 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.5b0422.js 3.81 kB
└ chunks/webpack.61f1b6.js 778 B
It appears to be a mature solution, with quite a number of users. The API is intuitive and very easy to use, great integration for React using hooks.
Version: 11.6 | Maintained by Robin Weser | Launched in 2016 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ Built-in Theming support
✅ Atomic CSS
✅ Framework agnostic
? TypeScript support : it exposes Flow types, which work ok, from our (limited) experience
? Context-aware code completion : styles defined outside the component require explicit typing to get code completion
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection a , b , ...)Fela looks to be a mature solution, with active development. It introduces 2 great features which we enjoyed a lot. The first one is the basic principle that "Style as a Function of State" which makes working with dynamic styles feel super natural and integrates perfectly with React's mindset. The second is atomic CSS class names, which should potentially scale great when used in large applications.
The lack of TS support however is a bummer, considering we're looking for a fully type-safe solution. Also, the scaling benefits of atomic CSS should be measured against the library bundle size.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 88.6 kB | 276 kB |
| vs. CSS Modules | +11.9 kB | +43 kB |
Page Size First Load JS
┌ ○ / 2.84 kB 81.7 kB
├ /_app 0 B 78.9 kB
├ ○ /404 194 B 79 kB
└ ○ /other 1.43 kB 80.3 kB
+ First Load JS shared by all 78.9 kB
├ chunks/framework.2191d1.js 42.4 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.32bc1d.js 12.6 kB
└ chunks/webpack.ddd010.js 822 B
Very young library, solid, modern and well-thought-out solution. The overall experience is just great, full TS support, a lot of other useful features baked in the lib.
Version: 0.2.5 (beta) | Maintained by Modulz | Launched in 2020 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Built-in Theming support
✅ Framework agnostic : (available with @stitches/core )
Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss prop (used only to override styled components)Styles output
.css file extraction<style> tag injection variants (for predefined styles), or styles created inside the component to get access to the propsStitches is probably the most modern solution to this date, with full out-of-the-box support for TS. Without a doubt, they took some of the best features from other solutions and put them together for an awesome development experience. The first thing that impressed us was definitely the documentation. The second, is the API they expose which is close to top-notch. The features they provide are not huge in quantity, but are very well-thought-out.
However, we cannot ignore the fact that it's still in beta. Also, the authors identify it as "near-zero runtime" , but at +9 kB gzipped it's debatable.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 82.0 kB | 250 kB |
| vs. CSS Modules | +5.3 kB | +17 kB |
Page Size First Load JS
┌ ○ / 2.43 kB 75.2 kB
├ /_app 0 B 72.8 kB
├ ○ /404 194 B 73 kB
└ ○ /other 984 B 73.8 kB
+ First Load JS shared by all 72.8 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.ff82f0.js 6.93 kB
└ chunks/webpack.61f1b6.js 778 B
Probably the grandaddy around here, JSS is a very mature solution being the first of them, and still being maintained. The API is intuitive and very easy to use, great integration for React using hooks.
Version: 10.7 | Maintained by Oleg Isonen and others | Launched in 2014 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ Built-in Theming support
✅ Framework agnostic
✅ TypeScript support
✅ Context-aware code completion
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled component (available with additional plugin)css propStyles output
.css file extraction<style> tag injection react-jss package, which is used with React/Next.js, depends on jss-preset-default, which includes many plugins by default, so you don't need to manually add some of the plugins;react-jss uses className by default. There's also styled-jss that uses Styled Components approach, but it has no types, and couldn't make it work on top of react-jss ;injectSheet API (or we couldn't find it anywhere);The API is similar in many ways to React Native StyleSheets, while the hooks helper allows for easy dynamic styles definition. There are many plugins that can add a lot of features to the core functionality, but attention must be payed to the total bundle size, which is significant even with the bare minimum only.
Also, being the first CSS-in-JS solution built, it lacks many of the modern features that focuses on developer experience.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 94.9 kB | 293 kB |
| vs. CSS Modules | +18.2 kB | +60 kB |
Page Size First Load JS
┌ ○ / 2.45 kB 88 kB
├ /_app 0 B 85.6 kB
├ ○ /404 194 B 85.8 kB
└ ○ /other 992 B 86.6 kB
+ First Load JS shared by all 85.6 kB
├ chunks/framework.2191d1.js 42.4 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.5f0007.js 19.2 kB
└ chunks/webpack.9c89cc.js 956 B
A very light-weight solution, with a loads of features.
Version: 2.0 | Maintained by Cristian Bote | Launched in 2019 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ Built-in Theming support
✅ TypeScript support
✅ Context-aware code completion
✅ Framework agnostic
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled component ( see details below )css prop ( is supported, but requires a separate babel plugin )Styles output
.css file extraction<style> tag injection <style> tag with all the styles, and appends to it on update, and apparently it doesn't use insertRule() , not even in production builds, which might be an important performance drawback in large & highly dynamic UIs Looking at Goober you cannot ask yourself what kind of magic did Cristian Bote do to fit all the features inside this tiny library. It is really mind blowing. It is marketed as being "less than 1KB" , which is not entirely accurate, but still... it's the smallest library we've tested.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 77.8 kB | 237 kB |
| vs. CSS Modules | +1.1 kB | +4 kB |
Page Size First Load JS
┌ ○ / 2.77 kB 71.1 kB
├ /_app 0 B 68.3 kB
├ ○ /404 194 B 68.5 kB
└ ○ /other 2.39 kB 70.7 kB
+ First Load JS shared by all 68.3 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.5ee014.js 2.42 kB
└ chunks/webpack.61f1b6.js 778 B
A rather new library, having the huge Atlassian platform supporting and probably using it. Many existing features, even more in development, or planned for development.
Version: 0.6 | Maintained by Atlassian | Launched in 2020 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Atomic CSS
Not Framework agnostic
No Built-in Theming support (at least at the moment, but it is planned)
Styles definition method(s)
Styles nesting
Styles apply method(s)
className (only supported with a custom ClassNames component)styled componentcss propStyles output
.css file extraction (currently under development, will be shipped in 2021)<style> tag injection css prop is seamless and trivial, not requiring any special setup (unlike Emotion) <head> during SSR - instead they are placed right before the element using them in the <body> , which could potentially provide slightly faster Paint metrics, such as FCP, or LCP, because the browser can start rendering the body faster and incrementally, not waiting for the entire block of styles to be parsedClassNames API, which enables us to apply styles as class name strings, is a bit convoluted and weird at first sight. Compiled is a very promising library. Considering that it offers both atomic CSS, and it plans to support static .css extraction, with excellent TypeScript support and style co-location, it would be quite unique (having only style9 as a direct competitor).
Also, we cannot ignore that is has Atlassian supporting its development, which puts a (slightly) bigger weight on the confidence level.
The total bundle overhead is pretty small, the runtime library being quite light-weight. With static .css file extraction, this could potentially become even smaller.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 80.2 kB | 242 kB |
| vs. CSS Modules | +3.5 kB | +9 kB |
Page Size First Load JS
┌ ○ / 2.11 kB 71.8 kB
├ /_app 0 B 66.5 kB
├ ○ /404 194 B 66.7 kB
└ ○ /other 888 B 70.6 kB
+ First Load JS shared by all 66.5 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.ebe095.js 576 B
├ chunks/webpack.ddd010.js 822 B
└ css/a92bf2d3acbab964f6ac.css 319 B
Linaria is all about static CSS extraction and avoiding any runtime overhead.
Version: 3.0 (beta) | Maintained by Callstack | Launched in 2018 | View Docs | ... Zurück zur Übersicht
✅ Styles/Component co-location
✅ TypeScript support
✅ Context-aware code completion
✅ Framework agnostic
✅ Built-in Theming support
No Atomic CSS
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection Linaria is highly inspired from Astroturf, combining various features from other libraries.
Version 3 is currently in Beta, not sure what the changelog is compared to v2. It's still in development by the React/Native geeks at Callstack.io , but we couldn't find which of the big players use it in production.
It seems to have a slightly larger overall page size ( 2.9 KB ), but we didn't investigate where does this come from. Also, there's an open question if this overhead is fixed or if it scales.
PS: thanks to Daniil Petrov for his PR with the Next.js integration
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 79.4 kB | 239 kB |
| vs. CSS Modules | +2.7 kB | +6 kB |
Page Size First Load JS
┌ ○ / 4.99 kB 71.5 kB
├ └ css/16f3e95ede28dcc048f2.css 423 B
├ /_app 0 B 66.5 kB
├ ○ /404 194 B 66.7 kB
└ ○ /other 3.59 kB 70.1 kB
└ css/3064299bff08067ec7dd.css 427 B
+ First Load JS shared by all 66.5 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.b2b078.js 23.1 kB
├ chunks/pages/_app.98e8c3.js 598 B
├ chunks/webpack.ddd010.js 822 B
└ css/7739287c04a618ea0c54.css 295 B
Modern solution with great TypeScript integration and no runtime overhead. It's pretty minimal in its features, straightforward and opinionated. Everything is processed at compile time, and it generates static CSS files. Successor of Treat, also be called "Treat v3", is developed and maintained by the same authors.
Version: 1.2 | Maintained by Seek OSS | Launched in 2021 | View Docs | ... Zurück zur Übersicht
✅ TypeScript support
✅ Built-in Theming support
✅ Context-aware code completion
✅ Framework agnostic
? Atomic CSS : can be achieved with Sprinkles
No Styles/Component co-location : styles must be placed in an external .css.ts file
Styles definition method(s)
Styles nesting
Styles apply method(s)
classNamestyled componentcss propStyles output
.css file extraction<style> tag injection & > span ), which might be seen as a downside, but it actually discourages bad-practices like specificity wars , which should be avoided when scaling CSS (however, this is impossible to be statically type-checked without pattern matching , so it will throw a runtime exception)variants based on predefined types, or inline styles for user-defined styles We felt a lot like using CSS Modules: we need an external file for styles, we place the styles on the elements using className , we handle dynamic styles with inline styles , etc. However, we don't write CSS, and the overall experience with TypeScript support is magnificent, because everything is typed, so we don't do any copy-paste . Error messages are very helpful in guiding us when we do something we're not supposed to do.
vanilla-extract is built with restrictions in mind, with a strong user-centric focus, balacing the developer experience with solid TypeScript support. It's also worth mentioning that Mark Dalgleish, co-author of CSS Modules, works at Seek and he's also a contributor.
The authors vision is to think of vanilla-extract as a low-level utility for building higher-level frameworks, which will probably happen in the future.
| Transferred / gzipped | Unkomprimiert | |
|---|---|---|
| Index page size | 76.7 kB | 231 kB |
| vs. CSS Modules | +0.0 kB | -2 kB |
Page Size First Load JS
┌ ○ / 2.09 kB 68.5 kB
├ └ css/37c023369f5e1762e423.css 370 B
├ /_app 0 B 66.4 kB
├ ○ /404 194 B 66.6 kB
└ ○ /other 611 B 67 kB
└ css/a56b9d05c6da35ff125f.css 386 B
+ First Load JS shared by all 66.4 kB
├ chunks/framework.895f06.js 42 kB
├ chunks/main.700159.js 23.1 kB
├ chunks/pages/_app.bfd136.js 565 B
├ chunks/webpack.61f1b6.js 778 B
└ css/23b89d9ef0ca05e4b917.css 286 B
We know there are a lot of other libraries out there, besides the ones covered above. We're only covered the ones that have support for React , support for SSR , an easy integration with Next.js , good documentation and a sense of ongoing support and maintenance . Please checkout our goals.
Treat was initially included in the analysis with v1.6, but removed for a few reasons:
The main difference between vanilla-extract and Treat is that the latter supports IE and legacy browsers as well.
Style9 is a new library, inspired by Facebook's own CSS-in-JS solution called stylex. Style9 is unique because it's the only open source library that supports both .css static extraction + atomic CSS, and/or styles co-location. It has TS support and easy to integrate with Next.js.
However, it has quite a few limitations (at least as of Feb 2021) that makes it practically unusable in a real production application that we would want to scale, both in code & team size:
Enum or POJO , only constant primitives are supported, which is a big deal breaker ;classNames lib, but not dynamically/computed/expression based;Some upsides:
As a conclusion, it wants to be a powerful solution with very interesting and unique set of features, but it's not mature yet. As far as we see, it's currently mostly designed towards more static solutions. Dynamic styling seems to be difficult to handle, at least for the moment.
Not an actual CSS-in-JS library, more like a replacement for traditional CSS styling. It uses atomic CSS classes (some of them having multiple properties) that we attach to html elements. We don't write CSS, instead we use a different DSL to specify styles, pseudo classes, media queries, etc.
The reason we didn't include it in our thorough review is because it doesn't fully meet our goals:
.ts files to include them in tailwind.config (cannot import any file, cannot require .ts )tailwind.config directly offers no type-safety when importing it, or using resolveConfigrounded , place-self/content , divide , ring )::after pseudo elements are trickySome upsides:
tailwind.configTailwind seems to be more than a styling tool , it also offers some out-of-the-box utils + a ready-made design system that you can use right away.
It's not a popular solution, the approach is similar to React Native StyleSheets way of styling components. Has built-in TypeScript support and a simple API.
I got it started with Next.js, but it feels fragile. The Glamor official example throws an error regarding rehydrate . When commenting it out, it works, but not sure what the consequences are.
Didn't manage to start it with Next.js + TypeScript. The official example uses version 3, while today we have version 6. The example doesn't work, because the API has changed.
The solution looked interesting, because it is supposed to be very light-weight.
Didn't manage to start it with Next.js + TypeScript. There was an official example that used an older version of Next.js, but the example if not there anymore.
The solution is not that popular, but it was the first to use .css extraction with collocated styles.
Looks promising, atomic css and light-weight. It has a working Next.js example, but we didn't consider it because it lacks any documentation.
It looks like a not so popular solution, which also lacks support for TypeScript. It looks like the maintainers work at Uber and they use it internally. It focused on generating unique atomic CSS classes, which could potentially deduplicate a lot of code.
The project was put in Maintenance Mode. They recommend other solutions.
The project was discontinued in favor of Emotion.
Each implementation sits on their own branch, so we can have a clear separation at built time.
# install dependencies
yarn
# for development
yarn dev
# for production
yarn build
yarn startTo get in touch, my DMs are open @pfeiffer_andrei.
Special thanks and appreciations go to everyone that helped putting this document together, and making it more accurate: