Blog

Tailwind: ein Utility-first Framework für CSS

Feb 25, 2022

Applikationscode mit Tailwind sieht im ersten Schritt furchtbar aus. Jedes Element hat sehr viele Klassen, die bestimmte Stylingaspekte beschreiben. Es fühlt sich sehr ausführlich an und mehr nach einem Rückschritt denn nach einem Schritt in die Zukunft. Doch was ist Tailwind überhaupt und womit sollte man es vergleichen? Diese und andere Fragen beantworten wir in diesem Artikel.

Kurz und knapp: Tailwind ist ein Low-Level CSS Framework, mit dem sich beliebige Layouts schnell und einfach umsetzen lassen. Eine etwas längere Antwort könnte lauten: Am ehesten ist Tailwind mit Lösungen wie Bootstrap oder Material UI vergleichbar. Diese haben allerdings den Nachteil, dass Applikationen, die mit ihnen umgesetzt werden, sehr ähnlich aussehen. Dieses Problem haben Sie bei Tailwind nicht, da es hier keine vorgefertigten Komponenten gibt, sondern lediglich Hilfsklassen, die Sie direkt im HTML-Code Ihrer Applikation verwenden und beliebig kombinieren können. Das Framework bietet also ein hohes Maß an Flexibilität und macht keine Einschränkungen, wenn es um das Styling Ihrer Applikation geht. Tailwind selbst macht auf seiner Webseite eine ganze Reihe von Versprechen, die wir uns im Folgenden im Detail ansehen. Darüber hinaus setzen wir Tailwind in einer kleinen Applikation ein, damit die Verwendung von der Installation über die Implementierung von Frontends bis zum Build der Applikation deutlich wird.

Was ist die Idee hinter Tailwind?

Tailwind ist ein Utility-first Framework. Es legt seinen Schwerpunkt auf die sogenannten Utility-Klassen und stellt, anders als andere Frameworks, keine vorgefertigten Komponenten zur Verfügung. Einige dieser Utility-Klassen kennen Sie aus anderen Frameworks wie beispielsweise Bootstrap, wo Sie mit den Spacing Utilitys die Innen- und Außenabstände festlegen können. So steht .mr-3 in Bootstrap für margin-right: 1rem;. Tailwind führt diesen Ansatz noch deutlich weiter und bietet für nahezu alle Aspekte des Stylings einer Webapplikation eine Lösung.

Die Arbeit mit dem Framework fühlt sich stellenweise stark nach (zu Recht) verpöntem Inline-Styling an. Auf den zweiten Blick stimmt das so jedoch nicht. Bei In-line-Styling haben Sie die Freiheit, aus allen verfügbaren Werten zu wählen. Die Utility-Klassen schränken diese Freiheit deutlich ein und bieten eine festgelegte Auswahl, beispielsweise für Abstände und Farben. Doch woher kommt unser schlechtes Gefühl, wenn wir das erste Mal auf eine HTML-Datei blicken, die mit Tailwind gestylt wurde? Adam Wathan, der Schöpfer von Tailwind, hat einen interessanten Blogartikel zu diesem Thema und seiner Reise auf dem Weg zu Tailwind geschrieben. Dem Ganzen liegt der Begriff Separation of Concerns zugrunde. HTML legt die Struktur der Webseite fest, CSS ist für das gute Aussehen zuständig und JavaScript kümmert sich um die Logik. Alle drei Elemente sind unabhängig voneinander und liegen in separaten Dateien.

Und dann kommen plötzlich Werkzeuge um die Ecke, die uns die Arbeit erleichtern sollen und brechen mit diesem zentralen Paradigma. Tailwind ist nicht das einzige Beispiel. Werfen wir doch mal einen Blick auf React beziehungsweise auf JSX. Ist JSX nicht auch nur eine Vermischung von JavaScript und HTML? Genau das ist es – aber mit dem Vorteil, dass React auf eine separate Template Engine verzichtet und der Code einer Komponente deklarativ und aus einem Guss entsteht. Natürlich können Sie in React auf JSX verzichten und Ihre Komponenten komplett mit React.createElement-Aufrufen übersähen, das macht nur in der Praxis kein Entwickler. Vielmehr gibt es Menschen, die JSX auch in anderen Kontexten wie beispielsweise in Vue-Applikationen einsetzen. Das Ganze fällt jedoch unter die Kategorie „persönliche Präferenz“.

Hinzu kommt, dass diese ganze Separation of Concerns-Geschichte nur oberflächlich funktioniert. In vielen Applikationen findet man Klassen wie profile-picture oder Ähnliches. Diese Klassen nutzt dann das Stylesheet der Applikation, um den Inhalt zu stylen. Damit hängt das Styling jedoch an der Struktur der Applikation und es liegt viel Wissen um die Struktur und den Aufbau des HTML-Dokuments im Stylesheet. Tailwind dreht das um und verschiebt das Wissen über Stylingdetails ins HTML. Aber führt das nicht zu sehr vielen Duplikaten im HTML? Diese Frage ist berechtigt, allerdings gibt es auch hierfür Lösungen. Tailwind verbietet Ihnen nicht, eigene Klassen zu erstellen. Gerade für die Fälle, in denen Sie die gleichen Styles einheitlich auf mehrere Elemente anwenden möchten und es sich nicht nur um eine oder zwei Klassen handelt, ergibt es Sinn, eine eigene CSS-Klasse zu definieren. Eine weitere Alternative besteht darin, einen komponentenbasierten Ansatz zu verfolgen. Dieser Architekturansatz bildet die Grundlage für die großen JavaScript Frameworks und Libraries wie React, Angular und Vue. In diesem Fall definieren Sie nicht an mehreren Stellen in Ihrer Applikation Button-Elemente und stylen sie, sondern Sie erstellen eine allgemeingültige Button-Komponente, die überall in Ihrer Applikation zum Einsatz kommt. Anpassungen an der Funktionalität oder dem Styling finden dann an einer zentralen Stelle statt und wirken sich auf die gesamte Applikation aus. Und damit wären wir auch schon beim nächsten Thema: Sie können Tailwind hervorragend mit diesen Frameworks zusammen nutzen. Bevor wir uns das am Beispiel von React ansehen, werfen wir zunächst einen Blick auf die Kernfeatures von Tailwind.

Installation und erste Schritte

Wie alle modernen Werkzeuge kann auch Tailwind über einen beliebigen Paketmanager wie npm oder Yarn installiert werden. Eine Alternative ist die Verwendung der bereits gebauten Variante im CDN. Diese Art unterliegt jedoch einigen Einschränkungen:

  • Sie können das Standard-Theme nicht anpassen.

  • Direktiven wie @apply sind nicht verfügbar.

  • Zusätzliche Varianten wie group-focus können nicht aktiviert werden.

  • Es werden keine Plug-ins unterstützt.

  • Nicht verwendete Styles können nicht per Tree Shaking entfernt werden.

Diesen Einschränkungen steht eine sehr einfache Einbindung entgegen: Sie fügen ein link-Element in Ihr HTML-Dokument ein und können sofort mit Tailwind starten. Die css-Datei ist unter [1] verfügbar. Diese direkte Einbindung ist gerade für kleine Applikationen und schnelle Prototypen empfehlenswert. Bei einer größeren Applikation sollten Sie Tailwind lokal installieren, damit haben Sie die volle Kontrolle über das Framework und können sämtliche Features nutzen. Mit nur wenigen Schritten können Sie Tailwind in Ihre Applikation einbinden:

  1. Installation: Mit dem Kommando npm install tailwindcss installieren Sie das Tailwind-Paket in Ihrer Applikation.

  2. Erstellen einer Konfiguration: Tailwind besteht nicht nur aus einer Reihe von CSS-Klassen, sondern stellt Ihnen auch ein Kommandozeilenwerkzeug zur Verfügung. Damit können Sie beispielsweise die initiale Konfiguration für Ihre Applikation erzeugen lassen. Das Kommando npx tailwindcss init erstellt die Datei tailwind.config.js im Wurzelverzeichnis der Applikation. Die Datei enthält lediglich eine Basisstruktur, die Sie je nach Anforderungen erweitern können. Dieser Schritt ist optional, da Tailwind in einfachen Projekten auch ohne diese Konfiguration funktioniert.

  3. Einbindung ins CSS Ihrer Applikation: Damit Sie in den Genuss von Tailwind in Ihrer Applikation kommen, müssen Sie das Framework in Ihre Applikation einbinden. Nachdem sich Tailwind nur auf der Ebene von CSS bewegt und keine weiteren HTML-Strukturen oder JavaScript-Logik mitbringt, beschränkt sich die Integration auf eine CSS-Datei. In diese fügen Sie zumindest den folgenden Quellcode ein:

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
  4. Tailwind arbeitet mit Direktiven, wie beispielsweise @tailwind, um dem Build-Werkzeug mitzuteilen, dass an dieser Stelle etwa die grundlegenden Klassen, Komponenten und Werkzeuge eingefügt werden sollen. Während des Build-Prozesses werden diese Direktiven durch nativen CSS-Code übersetzt.

  5. Bauen des CSS-Codes: Angenommen, die Datei aus Schritt 3 liegt in Ihrer Applikation im Verzeichnis src und hat den Namen style.css und Sie möchten, dass die Ausgabe im Verzeichnis dist in der Datei style.css abgelegt wird, dann nutzen Sie das Kommando npx [email protected] build ./src/style.css -o ./dist/style.css. Das Tailwind-CLI gibt Ihnen nach Abschluss des Build-Prozesses noch einige Informationen über den Prozess, wie beispielsweise die Zeit, die er in Anspruch genommen hat, wie groß die Ausgabedatei ist und wohin das Stylesheet gespeichert wurde. Entweder integrieren Sie Tailwind direkt in den Build-Prozess Ihrer Applikation, indem Sie es beispielsweise über webpack ausführen lassen, oder Sie erzeugen zumindest ein npm-Skript in Ihrer package.json. Damit Sie Tailwind mit dem Kommando npm run build:css ausführen können, fügen Sie die Zeile build:css“: „npx [email protected] build ./src/style.css -o ./dist/style.css in die scripts-Sektion Ihrer package.json-Datei ein.

  6. Einbinden des Stylesheets und Verwendung: Nach dem Build-Prozess können Sie die generierte CSS-Datei über ein gewöhnliches link-Tag in eine HTML-Datei Ihrer Applikation einbinden und Tailwind nutzen.

Ein einfaches Beispiel

Ein schöner Seiteneffekt von Tailwind ist, dass Sie nach dem initialen Set-up direkt im HTML-Code Ihrer Applikation arbeiten können und nicht immer zwischen HTML und CSS hin und her wechseln müssen. Verwenden Sie Tailwind, wird Ihnen als Erstes auffallen, dass die nativen Browserstyles nicht mehr angewendet werden. So besteht beispielsweise kein Unterschied mehr zwischen gewöhnlichem Text und einer Überschrift erster Ordnung. Der Grund hierfür ist, dass Tailwind die Bibliothek modern-normalize nutzt, um das CSS des Browsers zurückzusetzen und Unterschiede zwischen den Browsern auszubügeln. Tailwind bindet den CSS-Reset über die Direktive @tailwind base ein. Im nächsten Schritt werfen wir einen Blick auf ein einfaches Beispiel für die Verwendung von Tailwind: Wir stylen ein Kochrezept. In Abbildung 1 sehen Sie das Ergebnis.

springer_tailwind_1.tif_fmt1.jpgAbb. 1: Das Kochrezept mit Tailwind [2]

Die Utility-Klassen von Tailwind decken die meisten Standardfälle bereits ab, sodass sich ein solches einfaches Layout ohne Anpassung umsetzen lässt. Die Klassen decken die verschiedenen Bereiche im Layout einer Applikation ab und lassen sich in Kategorien unterteilen wie beispielsweise Spacing für die Innen- und Außenabstände, Sizing zum Festlegen von Höhen und Breiten, Typography zur Definition von Aspekten, die das Aussehen der Schrift betreffen, und Backgrounds für die Darstellung von Hintergründen.

Listing 1: HTML-Dokument mit Tailwind-Klassen

<!DOCTYPE html>
<html lang="en">
 
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
</head>
 
<body>
  <div class="container mx-auto my-2 p-2 rounded border">
    <h1 class="mb-3 font-bold text-2xl">Pizzateig</h1>
 
    <div class="flex space-x-8">
      <img src="pizza.jpg" alt="" class="filter blur-md" width="300">
      <div>
        <h2 class="mb-2 font-bold text-l">Zutaten</h2>
        <div class="bg-gray-200 rounded px-2">500 ml Wasser</div>
        <div class="px-2">1000g Mehl</div>
        <div class="bg-gray-200 rounded px-2">40g Hefe</div>
        <div class="px-2">20g Salz</div>
        <div class="bg-gray-200 rounded px-2">25ml Öl</div>
        <div class="px-2">1 Prise Zucker</div>
      </div>
    </div>
    <div>
      <h2 class="mt-8 mb-2 font-bold text-l">Zubereitung</h2>
      <p>Lorem ipsum...</p>
    </div>
  </div>
</body>
</html>

Listing 1 enthält den Quellcode des Beispiels mit dem Kochrezept. Die Grundvoraussetzung für die Arbeit mit Tailwind ist die Einbindung des erzeugten Stylesheets im Kopf des HTML-Dokuments. Das erste div-Element im body des Dokuments ist schon ein gutes Beispiel für den Einsatz von Tailwind, da es mit dem Zentrieren eines Elements eines der schwierigsten Probleme in CSS adressiert. Aber Spaß beiseite, die verschiedenen Klassen beziehen sich auf verschiedene Aspekte des Stylings.

Die container-Klasse ist beispielsweise dafür verantwortlich, dass die Breite des Elements anhand des aktuellen Breakpoints angepasst wird. Tailwind sorgt dafür, dass im large-Breakpoint bei einer Fensterbreite ab 1024 Pixeln das Container-Element eine Breite von 1024 Pixeln aufweist. Diese Breite wird bis zum nächsten Breakpoint, dem xl-Breakpoint bei 1280 Pixeln, stabil gehalten. Tailwind unterstützt die fünf Breakpoints, die in Tabelle 1 dargestellt sind.

Breakpoint Abkürzung Fenstergröße
Small sm 640px
Medium md 768px
Large lg 1024px
Extra Large xl 1280px
2x Extra Large 2xl 1536px

Tabelle 1: Breakpoints in Tailwind

Die nächsten beiden Klassen des div-Elements nach der container-Klasse stehen für Margins, also Außenabstände, und die p-2-Klasse definiert das Padding, also den Innenabstand. Diese Spacing-Klassen folgen einem einheitlichen Namensschema. Der erste Buchstabe steht für Margin (m) beziehungsweise Padding (p). Anschließend können Sie mit einem der folgenden Buchstaben festlegen, wo der Abstand angewendet soll:

  • t (top): oben

  • b (bottom): unten

  • l (left): links

  • r (right): rechts

  • x (x-Achse): links und rechts

  • y (y-Achse): oben und unten

Lassen Sie den Buchstaben weg, wird der Abstand auf alle vier Seiten angewendet. Danach folgen ein Bindestrich und eine Zahl, die für die Breite des Abstands steht. Dabei nutzt Tailwind keine absoluten Pixelbreiten, sondern arbeitet mit relativen Maßangaben, indem die Einheit Rem verwendet wird. So steht die Klasse p-2 beispielsweise für padding: 0.5rem;. Die Zahl gibt den Multiplikator von 0.125rem an. Diese Regel gilt sowohl für Spacing als auch für andere Aspekte, wie beispielsweise Sizes. Aber auch in anderen Bereichen, etwa der Schriftgröße, arbeitet Tailwind mit relativen Größen. Ein konkretes Beispiel sehen Sie in der Überschrift, dem h1-Element. Hier steht die letzte Klasse, text-2xl, für eine Textgröße von 1.5rem und einer Zeilenhöhe von 2rem.

Die beiden letzten Klassen des Container-Elements zeigen mit abgerundeten Ecken und einem einfachen Rahmen weitere Bereiche, für die Tailwind Klassen definiert. Sie sehen, dass Sie für einfache Styles sprechende Klassen nutzen können, und ein Leser Ihres Quellcodes erhält sehr schnell einen Eindruck, wie das Styling gestaltet ist. Sowohl rounded als auch border können mit Modifikatoren versehen werden, die den Border-Radius beziehungsweise die Rahmenbreite beeinflussen. Beide Informationen übersetzt Tailwind, wie die bisherigen auch, in relative Größen in der Einheit Rem.

Eine umfassende Liste der Kategorien und der einzelnen Aspekte finden Sie in der Dokumentation von Tailwind, die unter [3] erreichbar ist.

Der Production Build mit Tailwind

Auf den ersten Blick macht Tailwind keine schlechte Figur. Das ändert sich jedoch sehr schnell, wenn Sie einen Blick in die Developer-Tools Ihres Browsers und hier speziell auf den Netzwerk-Tab werfen. Unser kleines Beispiel hat eine Gesamtgröße von 4,8 MB und wird momentan auch nur so schnell ausgeliefert, weil sich Browser und Quellcode auf der gleichen Maschine befinden. Der Browser erlaubt Ihnen eine schwächere Verbindung zu simulieren. Wählen Sie beispielsweise eine schnelle 3G-Verbindung, kann sich die Wartezeit für unsere Rezeptseite auf knapp 30 Sekunden erhöhen – und das liegt ganz sicher nicht an dem umfangreichen Rezept, sondern an dem 4 MB großen Stylesheet. Der Grund hierfür wird schnell klar: Tailwind integriert sämtliche Klassen, egal, ob sie benötigt werden oder nicht, was am Ende zu einem riesigen Stylesheet führt. Es gibt jedoch eine recht elegante Lösung für dieses Problem: Sie können Tailwind anweisen, dass alle nicht benötigten Klassen aus dem Stylesheet entfernt werden sollen.

Damit das funktioniert, müssen Sie Tailwind zunächst über die Konfiguration mitteilen, wo die Dateien liegen, die Tailwind-Klassen beinhalten. Das erreichen Sie über die purge-Eigenschaft. Hier geben Sie die Dateien an, die Tailwind beim Build-Prozess durchsuchen soll. Sie können die Dateien entweder einzeln angeben oder Wildcards verwenden. Die Zeichenkette ./src/**/*.html bezieht beispielsweise alle HTML-Dateien im src-Verzeichnis mit ein. Damit Tailwind einen optimierten Build erstellt, müssen Sie vor dem Aufruf des Tailwind-build-Kommandos die Umgebungsvariable NODE_ENV auf den Wert production setzen. Da Sie diese Operation wahrscheinlich öfter als nur einmal durchführen werden, empfiehlt sich ein entsprechendes npm-Skript. Da Sie nicht sicher sein können, auf welchem System das Skript ausgeführt werden wird, sollten Sie das Paket cross-env mit dem Kommando npm install –D cross-env installieren. Es sorgt dafür, dass das Setzen von Umgebungsvariablen unabhängig auf allen Systemen funktioniert. Damit können Sie das Kommando cross-env NODE_ENV=production npx [email protected] build ./src/style.css -o ./dist/style.css ausführen. Das Ergebnis ist, dass das Stylesheet unseres Beispiels nicht mehr 4 MB groß ist, sondern lediglich 13 kB, also nur noch ein Bruchteil des ursprünglichen Umfangs. Die Ladezeit auf einer simulierten schnellen 3G-Verbindung schrumpft dadurch auf nur noch etwas mehr als 5 Sekunden, was jedoch hauptsächlich an dem Bild liegt, das in das Rezept eingebunden wird, und nicht mehr am Stylesheet. In einer umfangreicheren Applikation wächst das zugehörige Stylesheet in der Regel nicht mit dem Umfang des übrigen Quellcodes. Der Grund hierfür ist, dass das Styling der Applikation normalerweise durchgängig und konsistent ist, also die gleichen Klassen überall wiederverwendet werden. An einem bestimmten Punkt in der Entwicklung wächst das Stylesheet also kaum mehr weiter, da alle benötigten Klassen schon mindestens einmal an einer anderen Stelle verwendet wurden.

Eigene Klassen definieren

Werfen Sie einen Blick in die Applikation, werden Sie feststellen, dass sich die Klassen in der Zutatenliste wiederholen. Wird diese Liste länger, kopieren Sie auch immer wieder die Klassenliste. Bei einer Änderung des Stylings müssen Sie dann auch jede Stelle wieder anfassen. Um dieses Problem zu lösen, können Sie im einfachsten Fall Ihre eigenen Klassen definieren. Oder Sie gehen noch einen Schritt weiter und weisen dem Container, der die Zutaten enthält, eine eigene Klasse zu. Für dieses Beispiel erhält der Container den Klassennamen striped, da es sich um eine gestreifte Liste handelt. Im Stylesheet können Sie dann mit etwas CSS und der Unterstützung von CSS-Pseudoklassen die Elemente entsprechend stylen. In Listing 2 finden Sie den Quellcode des Stylesheets.

Listing 2: Eigene Klassen im Stylesheet

@tailwind base;
@tailwind components;
@tailwind utilities;
 
.striped div:nth-child(2n + 1){
  @apply bg-gray-200 rounded px-2;
}
 
.striped div:nth-child(2n){
  @apply px-2;
}

Die beiden Selektoren, die Sie hier definieren, sorgen dafür, dass für die div-Elemente, die im Element mit der Klasse striped liegen, bestimmte Styles angewendet werden. Der erste Selektor nutzt die Pseudoklasse nth-child(2n + 1), um alle ungeraden Elemente zu stylen, der zweite übernimmt alle geraden Kindelemente. Das @apply ist eine Direktive von Tailwind, die dafür sorgt, dass die danach folgenden Klassen aufgelöst und der entsprechende CSS-Code eingefügt wird. Mit diesem Vorgehen müssen Sie nicht auf die aus anderen Frameworks gewohnten Klassen wie beispielsweise btn-primary verzichten, sondern können diese nach Ihren eigenen Bedürfnissen aufbauen.

Weitere Pseudoklassen

Neben der nth-child Pseudoklasse sieht der CSS-Standard weitere solche Selektoren wie beispielsweise :focus und :hover vor. Im Gegensatz zu nth-child unterstützt Tailwind diese beiden auch nativ. Den Hover State können Sie mit Tailwind stylen, indem Sie der Tailwind-Klasse eines HTML-Elements die Zeichenkette :hover voranstellen. Gleiches gilt für den Focus State. In beiden Fällen gibt es hier eine Einschränkung: Nicht alle Tailwind-Klassen werden standardmäßig unterstützt. Der Grund hierfür liegt in der Größe des erzeugten Stylesheets. Würde Tailwind alle verfügbaren Pseudoklassen für alle Klassen unterstützen, wäre das generierte Stylesheet noch einmal deutlich größer als die vorigen 4 MB. Über die Konfigurationsdatei können Sie die Unterstützung der verschiedenen Klassen erweitern. Wollen Sie beispielsweise die backgroundImage-Klasse für den Hover State verfügbar machen, erreichen Sie das mit der Konfigurationsanpassung aus Listing 3.

Listing 3: background-Image für den Hover State verfügbar machen

module.exports = {
  // ...
  variants: {
    extend: {
      backgrounbackgroundImage: ['hover'],
    }
  },
}

Neben den bereits erwähnten Focus und Hover States unterstützt Tailwind noch eine Reihe weiterer Pseudoklassen wie beispielsweise ActiveDisabled oder Checked. Mit den Klassen Odd-child und Even-child haben Sie die Möglichkeit, Effekte wie in der Zutatenliste zu erzeugen. Für eine vollständige Liste der unterstützten Pseudoklassen werfen Sie am besten einen Blick in die Dokumentation [4].

Responsive Design in Tailwind

In eine ähnliche Richtung wie die Pseudoklassen geht die Unterstützung von Responsive Design. Responsive Design bedeutet in diesem Zusammenhang, dass sich das Layout Ihrer Applikation der Fenstergröße anpasst. Das Responsive Design von Tailwind arbeitet mit den gleichen Breakpoints, die auch bei der container-Klasse zum Einsatz kommen. Ähnlich wie bei den Pseudoklassen stellen Sie auch hier den eigentlichen Tailwind-Klassen ein Präfix voran, nur dass Sie hier mit den Breakpoint-Abkürzungen arbeiten. Als Demonstration einer Responsive-Umsetzung in Tailwind sorgen wir nun dafür, dass sich das Kochrezept in den Breakpoints kleiner als md, also einer Fenstergröße von unter 768 px, anders verhält als bei den größeren Breakpoints. Die Abbildung und die Zutatenliste sollen in der kleineren Ansicht untereinander angeordnet werden und die Abbildung zentriert werden. Listing 4 enthält den angepassten Quellcode des betroffenen Blocks.

Listing 4: Responsive Design im Kochrezept

<div class="flex md:flex-row flex-col  md:space-x-8">
  <img src="pizza.jpg" alt=""class="filter blur-md mx-auto md:mx-0" width="300">
  <div class="striped">
    <h2 class="mb-2 font-bold text-l">Zutaten</h2>
    <div>500 ml Wasser</div>
    <div>1000g Mehl</div>
    <div>40g Hefe</div>
    <div>20g Salz</div>
    <div>25ml Öl</div>
    <div>1 Prise Zucker</div>
  </div>
</div>

Wenn Sie sich mit Responsive Design beschäftigen, sollten Sie immer mobile-first arbeiten – also Ihre Applikation für die Verwendung auf mobilen Geräten optimieren, sodass dieses Design als Fallback verwendet wird. Für die Änderungen wenden Sie dann die Breakpoint-Klassen an. Das div-Element, das das Bild und die Zutatenliste enthält, war auch vor dem Umbau schon ein Flex-Container mit der Standard-Flex-Direction row, die dafür sorgt, dass die Elemente nebeneinander angeordnet werden. Den Zwischenraum definieren Sie mit der space-x-8-Klasse. Nachdem die Elemente für kleinere Bildschirme untereinander angeordnet werden sollen, wenden Sie die flex-col-Klasse an. Vor die flex-row– und space-x-8-Klasse setzen Sie die Abkürzung md:, damit beide Regeln erst ab der entsprechenden Fenstergröße Anwendung finden. Die Styles mit der Breakpoint-Angabe überschreiben die Standardstyles, sodass das Rezept in einem größeren Fenster einen anderen Aufbau aufweist.

Tailwind und React

Sie haben bereits gesehen, dass Sie Tailwind sehr einfach in ein HTML-Dokument einbinden können. Die Hürde, das Framework zu verwenden, ist also denkbar gering. Seine wahre Stärke spielt Tailwind jedoch aus, wenn es mit anderen Frameworks und Libraries verwendet wird, um Webapplikationen zu implementieren. Die Dokumentation von Tailwind enthält Installationsanweisungen für React, Vue, Laravel, Next.js, Nuxt.js und Gatsby. Über Communityprojekte kann Tailwind aber auch problemlos in eine Angular-Applikation eingebunden werden. Im nächsten Abschnitt werfen wir einen Blick auf die Integration von Tailwind in eine React-Applikation, damit Sie einen Eindruck bekommen, wie sich Tailwind in einer komponentenbasierten Architektur verhält.

Die Voraussetzung für eine reibungslose Integration von Tailwind in eine React-Applikation ist, dass sie mit Create React App aufgesetzt wurde. Dadurch wird sichergestellt, dass alle erforderlichen Werkzeuge für den Buildprozess vorhanden und korrekt konfiguriert sind. Anschließend müssen Sie Tailwind selbst sowie PostCSS und Autoprefixer mit dem folgenden Kommando installieren:

npm install -D [email protected]:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat [email protected]^7 [email protected]^9

PostCSS ist ein CSS-Postprozessor, der den von Tailwind erzeugten CSS-Code weiterbearbeiten kann. Ein Beispiel hierfür ist das Einfügen von herstellerspezifischen Präfixen zu bestimmten CSS-Regeln. Create React App sieht vor, dass Sie als Entwickler im Normalfall nicht in die Build-Konfiguration eingreifen können. Eine Ausnahme ist hier das Ejecten der Konfiguration. Dieser Schritt wird jedoch im Allgemeinen nicht empfohlen, da er Upgrades auf neuere Versionen von Libraries erschweren kann. Um trotzdem die Build-Konfiguration entsprechend anpassen zu können, ohne den Weg über das Eject zu gehen, gibt es Hilfsmittel wie CRACO (Create React App Configuration Override), die Ihnen den Zugriff auf die Konfiguration erlauben. CRACO installieren Sie mit dem Kommando npm install @craco/craco. Anschließend ersetzten Sie den Aufruf von react-scripts in der scripts-Sektion durch craco und zwar für alle Scripts bis auf eject. Für CRACO erzeugen Sie dann eine Konfigurationsdatei mit dem Namen craco.config.js im Wurzelverzeichnis der Applikation. In dieser Konfiguration integrieren Sie Tailwind und Autoprefixer. Den zugehörigen Quellcode finden Sie in Listing 5.

Listing 5: CRACO-Konfiguration für die Integration von Tailwind

module.exports = {
  style: {
    postcss: {
      plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
      ],
    },
  },
}

Nach dieser Vorarbeit können Sie direkt in die Arbeit mit Tailwind einsteigen, indem Sie die Konfigurationsdatei mit npx tailwindcss init erzeugen lassen. Auch hier ist wieder die purge-Eigenschaft das Interessanteste für uns, um das resultierende Paket möglichst klein zu halten. An dieser Stelle fügen Sie die folgenden Einträge ein: ‚./src/**/*.{js,jsx,ts,tsx}‘, ‚./public/index.html‘. Mit diesem Muster decken Sie sowohl JavaScript- als auch TypeScript-Dateien ab. Im Anschluss können Sie die Basisdirektiven von Tailwind einfach in die index.css-Datei im src-Verzeichnis integrieren und auf diese Weise Tailwind in Ihre Applikation einbinden. Zur Demonstration können Sie in Listing 6 die Übersetzung unseres Kochrezepts in eine React-Komponente sehen.

Listing 6: Die Recipe-Komponente

const Recipe = ({recipe}) => {
  return (
    <div className="container mx-auto my-2 p-2 rounded border">
      <h1 className="mb-3 font-bold text-2xl">Pizzateig</h1>
      <div className="flex md:flex-row flex-col  md:space-x-8">
        <img src={recipe.image} alt="" className="filter blur-md mx-auto md:mx-0" width="300" />
        <div>
          <h2 className="mb-2 font-bold text-l">{recipe.title}</h2>
          {recipe.ingredients.map((ingredient, index) => (
            <div key={index} className="odd:bg-gray-200 odd:rounded px-2">
              {ingredient}
            </div>
          ))}
        </div>
      </div>
      <div>
        <h2 className="mt-8 mb-2 font-bold text-l">Zubereitung</h2>
        {recipe.description.map((desc) => (
          <p>{desc}</p>
        ))}
      </div>
    </div>
  );
};
 
export default Recipe;

Die Rezeptdaten erhält die Komponente über Props. Ansonsten ist die Komponente nahezu eine 1:1-Übersetzung unseres initialen Beispiels. Der größte Unterschied besteht darin, dass die Zutaten als Array übergeben werden und die Komponente über dieses Array iteriert, um die einzelnen Zutaten darzustellen. In diesem Fall nutzt die Komponente die odd-Pseudoklasse. Damit Sie diese nutzen können, müssen Sie sie in der Tailwind-Konfiguration im Bereich variants aktivieren, denn Tailwind deaktiviert diese Pseudoklasse standardmäßig für alle Klassen, um den Speicherbedarf möglichst gering zu halten. In Listing 7 sehen Sie die Anpassung an der Konfiguration.

Listing 7: Erweiterung der Konfiguration, um die odd-Pseudoklasse zu unterstützen

module.exports = {
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {
      backgroundColor: ['odd'],
      borderRadius: ['odd'],
    },
  },
  plugins: [],
}

Ähnlich wie bei den Zutaten iterieren wir auch über die einzelnen Schritte des Rezepts, die in p-Elemente gerendert werden. Nach einem Produktions-Build liegt die Beispielapplikation bei einer Gesamtgröße von 1,4 MB, wovon etwas über die Hälfte auf das Bild entfallen. In diesem Gesamtpaket befinden sich neben dem Code unserer Applikation auch noch die Tailwind-Klassen und der Quellcode von React selbst. Und auch hier gilt wieder: der Umfang des CSS-Quellcodes steigt zu Beginn der Entwicklung mit dem Funktionsumfang der Applikation. Ab einem bestimmten Punkt, von dem an die meisten Klassen, die die Applikation benötigt, wiederverwendet werden, bleibt die Größe relativ konstant.

Fazit

Tailwind ist aktuell wohl eines der populärsten CSS-Frameworks. Noch kann es bei den Downloadzahlen mit Konkurrenten wie beispielsweise Bootstrap nicht mithalten, die Verbreitung und damit auch die Downloadzahlen steigen allerdings stetig an. Tailwind verfolgt im Gegensatz zur Konkurrenz einen CSS-only-Ansatz und beinhaltet keinen JavaScript-Quellcode. Ein weiterer bemerkenswerter Unterschied zu anderen Lösungen besteht darin, dass Tailwind keinerlei Vorgaben macht, was das Styling von Elementen angeht. Es gibt also keine Standardbuttons oder -eingabeelemente. Tailwind kümmert sich auch nicht um Themen wie Modals oder Carousels. Das bedeutet aber auch, dass eine Tailwind-Applikation immer einen individuellen Charakter hat.

Der Kritikpunkt, dass immer wieder auf die gleichen Informationen wie Abstände oder Farben zugegriffen wird, lässt sich relativieren, da Tailwind in diesen Bereichen Vorgaben macht. So werden Abstände nicht in absoluten Pixelwerten umgesetzt, sondern in relativen Abstufungen angegeben. Die Einstiegshürde in Tailwind ist relativ gering, das Framework lässt sich mit nur wenigen Handgriffen in eine bestehende Applikation integrieren und erfordert nur, dass Sie den einen oder anderen Blick in die Dokumentation werfen, welche Klassen Ihnen zur Verfügung stehen, und schon können Sie mit der Entwicklung starten.

 

Links & Literatur

[1] https://unpkg.com/[email protected]/dist/tailwind.min.css

[2] CC BY 2.0 (https://creativecommons.org/licenses/by/2.0/); Whitehouse, Phil: https://commons.wikimedia.org/wiki/File:Pizza_capricciosa.jpg

[3] https://tailwindcss.com/docs

[4] https://tailwindcss.com/docs/hover-focus-and-other-states

Immer auf dem Laufenden bleiben!
Alle News & Updates: