Badge-, Tag- und Chip-Komponenten-System mit Tailwind CSS aufbauen
AI generated
tw
Tailwind CSS · UI-Pattern · Badge & Chip
Badge-, Tag- und Chip-Komponenten-System
Konsistente Varianten und Design-Tokens statt hartkodierter Farben mit Tailwind

Badges, Tags und Chips wirken einzeln betrachtet wie triviale kleine Bauteile, doch sobald sie in einer größeren Anwendung an zig verschiedenen Stellen auftauchen, entscheidet ein konsistentes System aus Größen, Farbvarianten und klaren Regeln für Interaktivität darüber, ob die Oberfläche aufgeräumt oder chaotisch wirkt. Dieser Artikel zeigt, wie sich ein wiederverwendbares Badge- und Chip-System mit Tailwind CSS aufbauen lässt, das auf Design-Tokens statt auf hartkodierten Farben pro Einzelfall basiert und klar zwischen statischen Badges und interaktiven, entfernbaren Chips unterscheidet.

15 Min. Lesezeit Badge System Chip Komponente

1. Badge, Tag und Chip: drei ähnliche Begriffe mit unterschiedlicher Bedeutung

In der Praxis werden die drei Begriffe oft synonym verwendet, obwohl sie unterschiedliche Interaktionsmodelle beschreiben. Ein Badge ist ein rein informatives, statisches Element, das einen Status oder eine Kategorie anzeigt, etwa 'Neu' auf einem Produkt oder 'Aktiv' neben einem Nutzerkonto, und hat keinerlei eigene Klickbarkeit. Ein Tag beschreibt inhaltlich meist dasselbe visuelle Element wie ein Badge, wird aber häufig für Kategorisierung und Filterung verwendet, etwa als klickbares Schlagwort unter einem Blogartikel, das zu einer gefilterten Ansicht führt.

Ein Chip dagegen ist explizit interaktiv und trägt oft einen eigenen Entfernen-Button, etwa in einer Multi-Select-Eingabe, in der jede ausgewählte Option als eigenständiger Chip mit einem kleinen X-Icon dargestellt wird. Diese begriffliche Unterscheidung ist mehr als Wortklauberei: Sie bestimmt direkt, welche Interaktions-Zustände, Fokus-Ringe und ARIA-Rollen eine Komponente braucht. Ein System, das diese drei Fälle von Anfang an sauber trennt, spart später viel Aufwand gegenüber einer einzigen, überladenen Komponente, die alle drei Fälle mit bedingter Logik abdecken soll.

2. Konsistente Größen- und Farbvarianten für Status-Badges

Der häufigste Fehler bei Badge-Systemen ist eine wild wachsende Anzahl von Farbkombinationen, bei denen jede neue Komponente ihre eigene Interpretation von 'Erfolg-Grün' oder 'Warnung-Gelb' mitbringt. Ein sauberes System definiert stattdessen eine feste, kleine Anzahl semantischer Varianten, typischerweise Erfolg, Warnung, Fehler und Neutral, und jede Variante bekommt eine feste Kombination aus Hintergrund-, Text- und optional Randfarbe, die konsequent im gesamten Projekt wiederverwendet wird, statt bei jedem neuen Einsatzort neu entschieden zu werden.

Bei der Größe hat sich ein ähnlich striktes Muster bewährt: zwei bis drei feste Größenstufen, etwa sm mit px-2 py-0.5 text-xs und md mit px-2.5 py-1 text-sm, statt beliebiger Padding-Werte pro Einzelfall. Die Kombination aus Grundgerüst inline-flex items-center rounded-full font-medium bleibt für alle Varianten und Größen identisch, nur die Farb- und Größenklassen wechseln je nach gewählter Variante, was die Komponente insgesamt vorhersehbar und leicht erweiterbar macht.


<!-- Badge-Grundgerüst, wiederverwendbar für alle Varianten -->
<span class="inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium
             bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-400">
  <span class="h-1.5 w-1.5 rounded-full bg-emerald-500"></span>
  Aktiv
</span>

<span class="inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium
             bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-400">
  <span class="h-1.5 w-1.5 rounded-full bg-amber-500"></span>
  Ausstehend
</span>

<span class="inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium
             bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-400">
  <span class="h-1.5 w-1.5 rounded-full bg-red-500"></span>
  Fehlgeschlagen
</span>

3. Design-Token-basierte Farbzuordnung statt hartkodierter Farben

Statt in jeder einzelnen Komponente direkt Tailwind-Farbklassen wie bg-emerald-100 zu hartcodieren, lohnt es sich, eine zentrale Zuordnung von semantischer Bedeutung zu konkreter Farbklasse zu definieren, etwa in einer JavaScript- oder TypeScript-Konstante, die Status-Schlüssel wie success, warning, error und neutral auf feste Klassenkombinationen abbildet. Jede Stelle im Code, die einen Status-Badge rendert, greift dann auf diese zentrale Zuordnung zu, statt die Farbklassen erneut selbst zu wählen, was Inkonsistenzen zwischen verschiedenen Entwicklern und verschiedenen Stellen im Code von vornherein verhindert.

Dieser Ansatz zahlt sich besonders aus, sobald sich das Farbschema ändern soll, etwa weil ein neues Corporate-Design eine andere Warnfarbe vorschreibt. Mit einer zentralen Token-Zuordnung reicht eine einzige Aenderung an der Zuordnungstabelle, während hartkodierte Farbklassen an zig verschiedenen Stellen im Projekt einzeln gesucht und angepasst werden müssten. Die Token-Zuordnung sollte dabei nicht nur die Hintergrundfarbe, sondern auch Text- und Punktfarbe sowie die jeweilige Dark-Mode-Variante an einer Stelle bündeln, damit ein einzelner Token immer ein vollständiges, konsistentes Farbset liefert.

4. Entfernbare Chips mit Icon-Button

Ein entfernbarer Chip braucht neben dem eigentlichen Label-Text einen kleinen, gut treffbaren Entfernen-Button, meist ein X-Icon am rechten Rand des Chips. Wichtig ist, dass dieser Button ein eigenständiges, fokussierbares Element mit eigenem aria-label ist, etwa 'aria-label="Filter Größe M entfernen"', und nicht Teil desselben klickbaren Bereichs wie der restliche Chip, da beide unterschiedliche Aktionen auslösen: ein Klick auf den Chip selbst kann etwa eine Detailansicht öffnen, während ein Klick auf das X-Icon ausschließlich das Entfernen auslöst.

Visuell bekommt der Entfernen-Button meist eine eigene, dezente Hover-Fläche, etwa ein kleiner Kreis mit hover:bg-black/10, der nur beim Hover über genau diesem Button sichtbar wird, um die Klickfläche vom restlichen Chip abzugrenzen, ohne optisch aufdringlich zu wirken. Der Button-Innenraum sollte trotz kleiner sichtbarer Icon-Größe ein Mindestmaß an Padding besitzen, damit die tatsächliche Klickfläche auch auf Touch-Geräten komfortabel größer bleibt als das sichtbare X-Symbol selbst.

5. Badge (statisch) versus Chip (interaktiv) im Code unterscheiden

Im Code lohnt es sich, Badge und Chip als zwei getrennte Komponenten zu implementieren, auch wenn sie sich optisch nur in Details unterscheiden, weil beide unterschiedliche HTML-Grundelemente und ARIA-Anforderungen haben. Ein Badge wird meist als einfaches <span> gerendert, da es rein informativ und niemals fokussierbar ist. Ein Chip dagegen, sobald er selbst klickbar ist, etwa um einen Filter zu aktivieren oder zu deaktivieren, braucht ein echtes <button>-Element mit korrektem type="button", damit Tastatur-Fokus, Enter-Taste und Screenreader-Ansage automatisch korrekt funktionieren.

Eine gemeinsame Basis-Komponente mit einem Prop wie interactive kann intern zwischen span und button als Wurzelelement umschalten, was Code-Duplizierung vermeidet, ohne die semantische Korrektheit zu opfern. Wichtig ist dabei, dass Hover- und Fokus-Zustände ausschließlich auf der interaktiven Variante existieren: Ein statischer Badge sollte niemals einen hover:-Zustand besitzen, da das fälschlich Interaktivität suggerieren würde, wo keine vorhanden ist.

6. Barrierefreiheit bei Badges und Chips

Bei rein dekorativen Status-Punkten innerhalb eines Badges, wie dem kleinen farbigen Kreis im Code-Beispiel weiter oben, muss sichergestellt sein, dass die Farbe niemals die einzige Informationsquelle ist. Der begleitende Text 'Aktiv' oder 'Ausstehend' trägt die eigentliche Information, während der Farbpunkt lediglich eine zusätzliche visuelle Verstärkung darstellt, die für Screenreader-Nutzer ohnehin unsichtbar bleibt und deshalb auch kein eigenes aria-label benötigt, solange der begleitende Text vorhanden ist.

Bei interaktiven Chips mit Entfernen-Funktion muss der Fokus-Ring auf dem X-Button deutlich sichtbar sein, meist über Tailwinds focus-visible:ring-2, da Tastaturnutzer sonst nicht erkennen können, welcher von mehreren nebeneinanderliegenden Chips gerade fokussiert ist. Nach dem Entfernen eines Chips sollte der Fokus sinnvollerweise auf den nächsten verbleibenden Chip oder, falls keiner mehr vorhanden ist, auf ein sinnvolles Folgeelement wie das zugehörige Eingabefeld wandern, statt komplett verloren zu gehen und den Nutzer wieder ganz oben in der Seite zu platzieren.

7. Layout mehrerer Badges und Chips mit Flex-Wrap

Sobald mehrere Badges oder Chips nebeneinander dargestellt werden, etwa als Liste aktiver Filter oberhalb einer Produktliste, muss das umgebende Layout mit flex flex-wrap gap-2 auf eine variable Anzahl von Elementen reagieren können, ohne dass die Elemente ihre eigene feste Breite verlieren oder abgeschnitten werden. Ein reines flex ohne flex-wrap würde bei vielen aktiven Filtern zu horizontalem Overflow oder zu extrem gestauchten, unlesbaren Chips führen, weshalb flex-wrap bei jeder Chip-Sammlung praktisch immer gesetzt werden sollte.

Der Abstand zwischen den Chips sollte konsistent über gap-2 statt über individuelle Margin-Klassen pro Chip gesetzt werden, da Margins bei wechselnder Zeilenumbruch-Position leicht zu ungleichmäßigen Abständen zwischen den Zeilen führen. Bei sehr vielen gleichzeitig aktiven Chips, etwa mehr als zehn aktiven Filtern, lohnt sich zusätzlich eine 'Alle entfernen'-Aktion am Ende der Reihe, damit Nutzer nicht jeden Chip einzeln per X-Button entfernen müssen.

8. Dark-Mode-Anpassung für das gesamte Farbsystem

Im Light Mode funktionieren helle, gesättigte Hintergrundfarben wie bg-emerald-100 mit dunklerem Text wie text-emerald-700 gut, weil der Kontrast zwischen Hintergrund und Text hoch genug bleibt. Im Dark Mode führt dieselbe Kombination oft zu einem unangenehm hellen, aus dem dunklen Hintergrund herausstechenden Fleck, weshalb sich im Dark Mode eine transparente, gedämpfte Hintergrundfarbe wie dark:bg-emerald-500/15 in Kombination mit einer helleren Textfarbe wie dark:text-emerald-400 deutlich besser einfügt.

Diese Dark-Mode-Anpassung sollte fest im zentralen Token-System hinterlegt sein, wie im Abschnitt zu Design-Tokens beschrieben, statt bei jeder einzelnen Komponente separat definiert zu werden. Ein Token wie success liefert dann automatisch sowohl die Light-Mode- als auch die Dark-Mode-Klassen als feste Einheit, was verhindert, dass eine Komponente im Dark Mode versehentlich vergessen wird und dort in einer falschen, zu grellen Farbe erscheint.

9. Praxisbeispiel: Filter-UI mit kombinierten Badges und Chips

Ein typisches Praxisbeispiel, das Badges und Chips gleichzeitig nutzt, ist eine Produktfilter-Oberfläche: Statische Badges zeigen den Lagerstatus einzelner Produkte in der Liste, während eine Reihe entfernbarer Chips oberhalb der Liste die aktuell aktiven Filter darstellt, etwa Größe, Farbe und Preisbereich. Beide Elemente teilen sich dieselbe visuelle Grundsprache, etwa abgerundete Ecken und ähnliche Größenverhältnisse, unterscheiden sich aber klar in ihrer Interaktivität, was Nutzern intuitiv signalisiert, welche Elemente klickbar sind und welche rein informativ bleiben.

Bei der Umsetzung eines solchen Filter-Systems lohnt es sich, die aktiven Filter-Chips und ihre Entfernen-Aktion an einen zentralen Zustand zu binden, meist ein Array aktiver Filter-Objekte, aus dem sowohl die Chip-Liste als auch die eigentliche Filterlogik der Produktliste abgeleitet werden. So bleibt sichergestellt, dass ein entfernter Chip sofort und konsistent sowohl aus der visuellen Darstellung als auch aus der tatsächlichen Filterung verschwindet, ohne dass beide Zustände getrennt synchronisiert werden müssen.

Status Hintergrund (Light) Text (Light) Dark-Mode-Hintergrund
Erfolg bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15
Warnung bg-amber-100 text-amber-700 dark:bg-amber-500/15
Fehler bg-red-100 text-red-700 dark:bg-red-500/15
Neutral bg-slate-100 text-slate-700 dark:bg-slate-500/15
Info bg-sky-100 text-sky-700 dark:bg-sky-500/15

Mironsoft

Tailwind-CSS-Architektur, Design-Systeme und Performance

Tailwind-Frontends, die trotz tausender Utility-Klassen wartbar bleiben?

Wir prüfen bestehende Tailwind-Projekte auf aufgeblähte Klassenlisten, inkonsistente Design-Tokens und ungenutzte CSS-Reste und bauen daraus ein Design-System, das sich sauber skaliert statt mit jeder Komponente unübersichtlicher zu werden.

Design-System-Review

Tokens, Spacing-Skala und Komponentenkonsistenz auf Wartbarkeit prüfen.

Performance-Optimierung

CSS-Bundle-Größe, Purge-Konfiguration und Ladezeiten systematisch reduzieren.

Component-Architektur

Wiederverwendbare, gut strukturierte Komponenten statt Klassenlisten-Wildwuchs aufbauen.

10. Zusammenfassung

Badge-, Tag- und Chip-System mit Tailwind: Das Wichtigste auf einen Blick

Begriffsklarheit

Badge ist statisch und informativ, Tag kategorisiert oft klickbar, Chip ist explizit interaktiv mit eigener Aktion.

Design-Tokens

Zentrale Zuordnung von Status zu Farbklassen statt hartkodierter Farben in jeder einzelnen Komponente.

Entfernbare Chips

Eigenständiger, fokussierbarer Entfernen-Button mit eigenem aria-label, getrennt vom restlichen Klickbereich.

Semantik

Badge als span, interaktiver Chip als echtes button-Element für korrekte Tastatur- und Screenreader-Unterstützung.

11. FAQ: Badge-, Tag- und Chip-System mit Tailwind: Das Wichtigste auf einen Blick

1Was ist der wichtigste Unterschied zwischen Badge und Chip im Code?
Ein Badge wird als reines span ohne Interaktions-Zustände gerendert, ein Chip als echtes button-Element mit Fokus-Ring, Hover-Zustand und oft einem eigenen Entfernen-Button.
2Warum sollten Farben nicht direkt in jeder Komponente hartcodiert werden?
Weil sich Farbänderungen dann an vielen verschiedenen Stellen im Code wiederholen und leicht inkonsistent werden. Eine zentrale Token-Zuordnung erlaubt eine einzige Änderungsstelle für das gesamte System.
3Wie viele semantische Farbvarianten sollte ein Badge-System mindestens haben?
Vier Grundvarianten decken die meisten Fälle ab: Erfolg, Warnung, Fehler und Neutral. Zusätzliche Varianten wie Info lassen sich bei Bedarf ergänzen, sollten aber die Gesamtzahl nicht unnötig aufblähen.
4Muss der Entfernen-Button eines Chips ein eigenes Element sein?
Ja, unbedingt. Wenn der gesamte Chip und der Entfernen-Button denselben Klick-Handler teilen, lassen sich unterschiedliche Aktionen wie Detailansicht öffnen und Entfernen nicht mehr sauber trennen.
5Wie stellt man sicher, dass Farbe nicht die einzige Informationsquelle ist?
Jeder farbcodierte Status braucht einen begleitenden Textlabel wie Aktiv oder Fehlgeschlagen. Die Farbe selbst dient nur als zusätzliche visuelle Verstärkung, niemals als alleinige Informationsquelle.
6Wie geht man mit sehr vielen aktiven Filter-Chips um?
Ab etwa zehn gleichzeitig aktiven Chips lohnt sich eine zusätzliche Alle-entfernen-Aktion am Ende der Reihe, damit Nutzer nicht jeden Chip einzeln entfernen müssen.
7Sollten Badge und Chip dieselbe Basiskomponente teilen?
Das ist sinnvoll, solange ein Prop wie interactive intern zwischen span und button als Wurzelelement umschaltet. Wichtig ist, dass Hover- und Fokus-Zustände ausschließlich in der interaktiven Variante existieren.
8Wohin sollte der Fokus nach dem Entfernen eines Chips wandern?
Idealerweise auf den nächsten verbleibenden Chip oder auf ein sinnvolles Folgeelement wie das zugehörige Eingabefeld. Der Fokus sollte niemals komplett verloren gehen und den Nutzer an den Seitenanfang zurücksetzen.
9Warum braucht Dark Mode eine eigene Farbkombination statt nur dunklerem Hintergrund?
Helle, gesättigte Light-Mode-Farben wirken im Dark Mode oft unangenehm grell. Eine transparente, gedämpfte Hintergrundfarbe mit hellerem Text fügt sich deutlich besser in eine dunkle Oberfläche ein.
10Wie verhindert man ungleichmäßige Abstände bei umbrechenden Chip-Reihen?
Der Abstand sollte konsistent über gap-2 auf dem umgebenden flex-Container gesetzt werden, nicht über individuelle Margin-Klassen pro Chip, da Margins bei wechselndem Zeilenumbruch leicht uneinheitlich wirken.