Ich bin hier nicht, um einen Schutzschild für CSS-Utility-Frameworks hochzuhalten. Ich mag diesen Ansatz selbst nicht besonders, und nichts ist über faire Kritik erhaben. Aber *fair* ist hier ein Schlüsselwort. Ich kann Ihnen nicht sagen, wie oft ich Utility-Styles mit Inline-Styles verglichen habe. Sarah Dayan hat es satt
[...] trotz zahlreicher Versuche, gängige Trugschlüsse zu widerlegen, müssen Enthusiasten von Utility-First weiterhin eine erstaunliche Menge an Missverständnissen richtigstellen. Und mit Abstand **ist das am meisten abgenutzte, überstrapazierte Klischee, dass Utility-Klassen nur Inline-Styles sind.**
Ich denke, dieser Vergleich wird es verdeutlichen
<div style="color: #3ea8ca;"></div>
<div class="color-blue"></div>
Das erste div hat eine `color`, die direkt in HTML gesetzt ist, und zwar ein extrem spezifischer Blautonwert. Das zweite hat eine `color`, die außerhalb von HTML gesetzt wird, mittels eines Klassennamens, mit dem Sie die Blautönung in CSS konfigurieren können. Sicher, die zweite ist ein ziemlich eingeschränkter Klassenname, da er, wie der Name schon sagt, nur eine Aufgabe erfüllt, aber er bietet immer noch eine gewisse Abstraktion, da die blaue Farbe geändert werden kann, ohne das Markup zu ändern. Es ist die gleiche Geschichte mit einer Utility-Klasse für Größen, sagen wir `size-xl`. Das ist auch eine Abstraktion, die wir verwenden könnten, um den Abstand eines Elements in CSS zu definieren, indem wir diesen Klassennamen als Selektor verwenden. Aber wenn wir `style="padding: 10px;"` direkt auf dem Element in HTML verwenden würden, ist das eine absolute Angabe, die eine Änderung des Wertes im Markup erfordert.
Um fair zu sein (was wir ja wollen), gibt es ziemlich viele Klassen in Utility-Frameworks, die so benannt sind, dass sie extrem nah an Inline-Styles agieren. Zum Beispiel bedeutet `top-0` in Tailwind `top: 0`, und es gibt keine Konfiguration oder Abstraktion dafür. Es ist nicht so, dass diese Klasse in CSS mit einem anderen Wert als Null aktualisiert wird, weil es im Namen steht. "Utility" ist eine gute Beschreibung dafür. Es ist sehr ähnlich wie ein Inline-Style.
All diese mit intelligenten Standardwerten konfigurierbaren Dinge bringen Utility-basierte Frameworks in eine andere Kategorie. Inline-Styles bieten keine Einschränkungen, wie Sie Dinge gestalten (außer harten Einschränkungen wie keine Pseudoelemente oder Media Queries), während eine begrenzte Anzahl von Utility-Klassen ziemlich viele Styling-Einschränkungen bietet. Diese Einschränkungen sind oft *wünschenswert*, da sie zu einem konsistenten und ansprechenden Design führen, anstatt zu einem inkonsistenten und schlampigen.
Um eine Metapher zu verwenden, die ich einmal in einem leicht anderen Kontext gehört habe: **Frameworks mit Utility-Klassen sind wie Banden-Bowling für Styling.** Verwenden Sie die Klassen, und es wird schon gutgehen. Sie werden vielleicht keinen Strike erzielen, aber auch keinen Gutterball.
Eine weitere unfaire Kritik, die ich in Gesprächen über Utility-Frameworks höre, ist, dass **man viel mehr CSS mitliefert.** Wenn Sie das tun, dann machen Sie definitiv etwas falsch. Meiner Meinung nach besteht der Hauptzweck dieses Ansatzes darin, *weniger* CSS auszuliefern (nur die Klassen, die Sie verwenden). Ich werde als Erster sagen, dass ein Build-Prozess, der dies genau und perfekt tut, tricky ist und zu einer ungesunden Menge technischer Schulden führen könnte, aber ich gebe zu, dass das Ausliefern von weniger CSS gut für die Leistung ist, wenn man es richtig macht. Tailwind ermutigt und hilft insbesondere dabei.
All das gesagt, denke ich, dass es alle möglichen Dinge gibt, die man an diesem Ansatz kritisieren kann. Zum Beispiel mag ich es persönlich nicht, all diese Klassen anzusehen. Ich mag es einfach nicht. Ich bin kein Absolutist, was perfekt abstrakte Klassen angeht, aber 10-20 Klassen auf einem Div nach dem anderen zu sehen, stört mich bei dem, was ich beim Templating von HTML tun möchte. Es fühlt sich schwieriger an, zu refaktorieren. Es fühlt sich schwieriger an, semantisch zu verstehen, was vor sich geht. Es ist schwieriger, diese Liste nach anderen Klassen zu parsen, die ich für nicht-stilistische Dinge benötige. Einige der Vorteile, die ich von Utilities erhalte, wie z. B. das Isolieren von Stilen genau dort, wo ich sie brauche, erhalte ich oft durch andere Werkzeuge.
Ich denke auch, dass Utility-Frameworks am besten in JavaScript-Komponenten-Setups mit Hot Module Reloading funktionieren. Andernfalls neigen HTML-Änderungen dazu, eine vollständige Seitenaktualisierung auszulösen. Zum Beispiel ist ein Tool wie Browsersync ziemlich gut. Es injiziert CSS, wenn sich Ihr CSS ändert. Aber es kann keine neuen HTML-Injektionen durchführen; es aktualisiert nur die Seite. Ohne Hot Module Reloading, was im Allgemeinen nicht für Ihre generischen HTML-Websites oder Static Site Generators gilt, erhalten Sie eine schlechtere DX während der Entwicklung.
Ich denke, der Punkt im Vergleich ist, dass die *Probleme* mit Inline-Styles die gleichen sind wie bei Utility-Klassen. Offensichtlich sind sie syntaktisch unterschiedlich, aber die Tatsache, dass man abstrahieren kann, was "blau" bedeutet, löst (zumindest für mich) nicht wirklich die Hauptprobleme von Inline-Styles (die Verletzung der Trennung von Belangen und des DRY-Prinzips). Ich meine, wenn Abstraktion wirklich das einzige Problem wäre, könnte man immer
was meiner Meinung nach nicht viel besser ist und sich nicht von
Es ist tatsächlich sehr ähnlich, aber es gibt einen großen Unterschied zwischen den beiden.
Es nennt sich Content Security Policy, kurz CSP.
Die Verwendung von `style` ist ein sofortiges Sicherheitsrisiko, während die Verwendung einer Klasse zu 100 % in Ordnung ist.
Fürs Protokoll: Ich mag beide Methoden nicht, da ich das Gefühl habe, dass sie eine harte Verknüpfung zwischen den Stilen und dem Inhalt herstellen, was für mich schlecht für die Trennung von Belangen ist. Ich wollte nur darauf hinweisen, dass die Verwendung von `style` größere Nachteile hat als die Verwendung einer Utility-Klasse.
IMO funktionieren Utility-CSS-Frameworks am besten mit komponentenbasierenden Frameworks. Ich denke, so bleibt man DRY.
Wenn ich Dinge wie React verwende, mache ich immer eine Eins-zu-Eins-Zuordnung zwischen meiner Komponente und ihrem Stil und verwende niemals CSS, das mehrere Komponenten überspannt.
Wenn ich ein UI-Muster habe, das sich wiederholt und gleich aussehen muss (Icon + Text, Button etc...), dann extrahiere ich es einfach als wiederverwendbare Komponente mit eigenem Stil.
Ich denke, in diesen Fällen ändert es nicht wirklich viel, ob Sie Ihr CSS in einer separaten Datei deklarieren, Styled Components verwenden oder Utility-CSS-Frameworks verwenden, da Ihr CSS sowieso nur an ein einziges Stück HTML-Template gebunden ist.
Ich sehe das nicht als skalierbar an. Müssen Sie wirklich für jeden HTML-Primärtyp, der einen bestimmten Stil benötigt, eine völlig neue Komponente erstellen? Es scheint, dass die Steuerung der Stile für die meisten Dinge außer Layout-Vorlagen und Komponenten in einem Stylesheet weitaus einfacher wäre. Ich sehe nicht, wie das
besser ist als einfach
Wenn wir nun über echte Abstraktionen von einzigartigen, wiederverwendbaren Mustern sprechen, ist das eine Sache. Ich würde immer noch semantische Klassen, Trennung von Belangen, Stylesheets als SSoT usw. bevorzugen, aber meiner Meinung nach wäre es zumindest besser, als für alles, was HTML und CSS kostenlos bieten, neue Komponenten erstellen zu müssen.
Ich stimme Jace Cotton zu.
Plus: Die sogenannte Utility belastet die Entwickler mehr, man muss sie lernen, aber in Wirklichkeit sollte CSS-Wissen ausreichen, da Utility = Inline ist.
Daher, was ist der Sinn? Lernen Sie, wie man Klassen benutzt, bevor Sie sie schreiben. Sie haben auf allen Seiten einen Header, CSS wird auf allen Seiten benötigt => externe Nutzung. Sie benötigen spezifisches CSS auf einer Seite, verwenden Sie ein zusätzliches Stylesheet, inline oder extern. Warum müssen Sie die Dinge komplizierter machen? Sie planen, 10 Module hinzuzufügen, was bedeutet, dass Sie Ihren Ansatz überdenken und 1 Modul mit 10 Modulen plus 1 Inline- oder externem CSS bedienen müssen. Sie wollen etwas Dynamisches tun = Chaos, da Sie dem Kunden niemals erlauben sollten, zu entscheiden, wie Ihre Website aussieht => sie sind keine Designer, sie wissen meistens nicht, was sie wollen usw.
Ich denke, Tailwind hat den Utility-Ansatz ziemlich gut umgesetzt.
Die beiden größten Kompromisse bei Utility-Frameworks sind meiner Meinung nach, dass sie die Reaktion auf Media Queries umständlich machen und dass jede Utility wirklich nur eine Sache tun sollte.
Ich mag den Ansatz auch nicht, aber wieder, eine automatisierte Lösung wie Tailwind löst die Probleme, die sie lösen will, ziemlich gut.
Die Verwendung von Tailwind in HTML ist großartig für Prototyping oder kleine Variationen vordefinierter Klassen, aber nicht gut, um sie in der Produktion zu belassen. Ich empfehle die Verwendung von `@apply` in Ihrem CSS, damit Sie gemeinsame Stile bereinigen und zusammenführen können und auch, damit Sie Tools wie Browsersync verwenden können.
Das ist, was wir tun. Schnell mit Inline-Utilities von Tailwind prototypisieren, dann `— -purge` verwenden, um nur das zu behalten, was wir brauchen, und bis zur Produktion werden viele der Klassen mit `@apply` hinzugefügt. Hält die Dinge relativ sauber, und wenn ich zufällige einmalige Änderungen vornehmen muss, ist es in Ordnung, ein paar grundlegende Utilities verstreut zu lassen.
Ein Problem, das manche vielleicht denken, ist, dass man, selbst wenn man unbenutztes CSS entfernt, mehr HTML ausliefern muss. Zum Beispiel hat ein kleines Projekt von mir, das Tailwind verwendet, eine Komponente, die eine 77 Zeichen lange Klasse verwendet, und diese Komponente wiederholt sich 24 Mal auf einer Seite, sodass sich das in dem generierten HTML summiert. Größere Projekte haben möglicherweise Komponenten, die sich viel öfter wiederholen als diese.
Wenn Sie Client-seitiges Rendering verwenden, ist dies kein Problem, da diese Klassen einmal in den Komponenten definiert sind. In anderen Fällen kann die Verwendung von Tailwinds `@apply` zur Reduzierung mehrerer verwendeter Klassen in eine einzige helfen.
**ABER** Ich denke nicht, dass das ein großes Problem ist: HTML wird sowieso komprimiert. Gzip ist großartig, Brotli leistet Wunder. Wenn Sie keines von beiden verwenden, machen Sie auch etwas falsch.
Ich denke, es ist sehr gut, aber wie der Autor sagte, nur für Umgebungen mit HMR und für JS-zentrierte Umgebungen, denn bei diesem Ansatz ist der einzige Weg, eine Gruppe von Stilen (aka Utility-Klassen) zu abstrahieren, die Erstellung einer JS-Komponente. Keine mehreren Dateierweiterungen. Keine Zwischenbibliotheken. Sie wollen eine Abstraktion? Sie erstellen eine JS-Datei dafür. Und ich denke, das ist eine ziemlich nette "Zusammenführung von Belangen".
Danke für die Adressierung dieser Problematik. Während es bei einfachen Beispielen wenige Abstraktionen gibt, verwendet man mehr, wenn man Dinge wie Media Queries nutzt. Um zum Beispiel ein Grid mit fünf Spalten zu erstellen, wenn die Bildschirmgröße über dem angegebenen großen Breakpoint liegt, ist es in Tailwind einfach
Das beinhaltet die Media Query und alles. Im Vergleich dazu ist das CSS dafür
Das CSS ist viel länger, und mit Inline-Styles kann man nicht einmal Media Queries durchführen. Ich respektiere jedoch die Trennung von Belangen, obwohl es mit Tailwinds `@apply` immer noch möglich ist, die Abstraktionen zu nutzen, die responsives Design erleichtern.
Der Vanilla-CSS-Ansatz könnte definitiv komprimiert werden. Erstens wird die `minmax()`-Funktion dort nicht benötigt. Zweitens kann man die `repeat`-Anzahl als Variable abstrahieren, sodass die Einrichtung anderer Spaltenlayouts nach der anfänglichen Einrichtung extrem prägnant wäre.
Ich denke, ein aufschlussreicheres Vergleichs-/Beispiel wäre so etwas wie
vs
(Vorausgesetzt natürlich Sass, aber es könnte auch ohne gehen.)
Während der Vanilla-Ansatz offensichtlich weniger prägnant ist, bietet er auch weitaus mehr Flexibilität (z. B. wenn man keine gleichgroßen Spalten haben möchte), und die höhere "Exaktheit", die für die Einrichtung erforderlich ist, hilft mir, ihn besser zu verstehen und fühlt sich einfach viel befreiender an.
Ich stimme Ihrer Einschätzung, dass "Frameworks mit Utility-Klassen wie Banden-Bowling für Styling sind", vollkommen zu. Tatsächlich würde ich das sogar bevorzugen.
Es geht darum, konsistente Muster und Bausteine für das Design zu verwenden.
Ein Argument ist die DRY-Prinzip. Sie können dafür durchaus `@import`-Anweisungen in Ihren CSS-Klassen verwenden.
Utility-Klassen sind großartig für Utility-Stile. Sie sind weniger großartig für andere Stile. Alle Dinge hier sind wahr und fair. Aber es ist auch das Problem der Kompositionsschichtung. Wenn Sie etwas Wiederholendes mit denselben 15 Low-Level-Utility-Klassen neu zusammensetzen müssen, werden die Dinge weniger überschaubar.
Die beiden Hauptprobleme, die ich mit "Utility-Klassen" habe (ehrlich gesagt: Tailwind ist die einzige, die ich ausprobiert habe), haben beide mit der Leistung zu tun.
Erstens, klar, das CSS ist kleiner – oft um ein Vielfaches kleiner –, aber das geht auf Kosten einer aufgeblähten Dokumentgröße (all diese Klassennamen summieren sich). Sicher, wir sprechen wahrscheinlich von einer (richtig getrimmten) CSS-Datei, die Hunderte von kB kleiner ist als ein "normaler" Codierungsstil wie (A)BEM oder SMACSS, gegenüber HTML, das "nur" wenige kB größer ist. Aber was davon wird nach dem ersten Besuch der Website vom Browser gecacht? Richtig: CSS.
Das andere Problem, das ich habe, ist, dass mit dem Aufkommen von HTTP/2, Server-Push und modularen Komponenten die All-in-One-CSS-Dateien aussterben. Stattdessen ist die Zukunft von CSS in mehreren kleineren CSS-Dateien, die jeweils speziell abgestimmt und angepasst sind, um eine einzelne Komponente einer Website zu stylen. Nun, dieser Ansatz schließt die Verwendung von Tailwind (et al.) nicht aus, aber er macht es *kontraproduktiv*, dies zu tun: Anstatt einer `.top-0 { top: 0; }`-Regel in einer All-in-One-CSS-Datei hätten Sie wahrscheinlich etwas wie eine in jeder einzelnen CSS-Datei. Multiplizieren Sie das mit der Vielzahl von Utility-Klassen, die wahrscheinlich in mehr als einer Komponente verwendet werden, und das Endergebnis ist massive, unnötige Bloat ohne Grund.
Ich habe den Bedarf an CSS-in-JS nicht verstanden. Und ich habe aufgehört, Atomic CSS-HTML seit 2016 zu verwenden.
Trennung von Belangen
Hässliches und unleserliches HTML
Mehr Schwierigkeit, Responsivität zu erreichen
CSS bietet Antworten mit Modulen und Variablen. Daher ist die Verwendung von Atomic oder Tailwind Overkill.
Bleiben Sie KISS, mit weniger Bibliotheken, weniger Frameworks. CSS-Frameworks helfen Ihnen nicht viel.
Ich habe Tailwind ziemlich gehypt, aber jetzt, nachdem ich es tatsächlich in einer echten Produktions-App verwendet habe, muss ich sagen, dass ich es irgendwie bereue.
Sehr lange Klassennamen, ganz zu schweigen davon, dass es einfach unbekannt ist, wie man die Klassen sinnvoll anordnet.
Dinge wie Stilvarianten sind in Tailwind tatsächlich viel schwieriger, man landet mit diesen Klassen-Join-Helfern, was mir irgendwie bizarr vorkommt.
Ich habe die Idee, dass man eine spezielle CSS-Syntax für eine Gruppe von atomaren Klassen hat, die man dann auf ein Element anwenden kann, etwas anders als bei `@apply`, wo es Styling extrahiert.
Der Vorteil, den ich sehe, ist, dass man die einzelnen Klassen leicht organisieren kann und dass es auch ermöglicht, diese Gruppen zu komponieren.
Es könnte auch helfen, Varianten zu komponieren, aber das muss ich erst in der Praxis sehen.
Um fair zu sein, es ist immer noch ein großartiges Werkzeug, zumindest für Prototypen. Tailwind Play ist etwas, das ich oft besuche, um bestimmte Komponenten und Ideen zu prototypisieren.
Svelte ist einen Blick wert.
Es nimmt Stile von allem auf, was in einem `