Halbe Sterne, Hover-Vorschau und Barrierefreiheit mit Tailwind sauber umsetzen
Sternebewertungen wirken auf den ersten Blick wie eine triviale Komponente, doch sobald halbe Sterne, eine interaktive Eingabe mit Hover-Vorschau und eine barrierefreie Umsetzung gleichzeitig gefordert sind, stecken mehr Detailprobleme darin als man denkt. Dieser Artikel zeigt, wie sich sowohl die read-only Anzeige einer Durchschnittsbewertung als auch die editierbare Eingabe-Variante mit Tailwind CSS sauber umsetzen lassen, inklusive der präzisen Darstellung halber Sterne und einer Barrierefreiheit, die nicht allein auf visuellen Sternen beruht.
Inhaltsverzeichnis
- 1. Warum Sternebewertungen mehr Sorgfalt brauchen als man denkt
- 2. Sterne mit Gradient-Fill als Füllstands-Basis
- 3. Halbe Sterne: Clip-Path versus Gradient im Vergleich
- 4. Interaktive Hover-Vorschau bei der Bewertungs-Eingabe
- 5. Read-only-Anzeige versus editierbare Eingabe
- 6. Barrierefreiheit: aria-label statt reiner visueller Darstellung
- 7. Größenvarianten für unterschiedliche Kontexte
- 8. Farbthemen und Dark-Mode-Anpassung
- 9. SVG-Icons versus Icon-Fonts für Sterne
- 10. Zusammenfassung
- 11. FAQ
1. Warum Sternebewertungen mehr Sorgfalt brauchen als man denkt
Eine Sternebewertung transportiert auf sehr kleinem visuellem Raum eine präzise numerische Information, meist eine Zahl zwischen null und fünf, oft mit einer Nachkommastelle. Genau diese Präzision macht die Umsetzung anspruchsvoller als bei den meisten anderen UI-Komponenten: Ein Durchschnittswert von 3.7 muss visuell auch tatsächlich als 3.7 und nicht als grob gerundete 4 erkennbar sein, sonst verliert die Bewertung an Aussagekraft. Gleichzeitig muss dieselbe visuelle Sprache sowohl für eine rein lesende Anzeige als auch für eine interaktive Eingabe funktionieren, bei der Nutzer per Hover und Klick selbst eine Bewertung abgeben.
Hinzu kommt, dass Sterne als rein visuelles Symbol grundsätzlich ein Barrierefreiheits-Problem darstellen, wenn die zugrundeliegende Zahl nicht auch textuell zugänglich gemacht wird. Wer nur fünf gefüllte oder leere Symbole ins DOM schreibt, macht die Bewertung für Screenreader-Nutzer faktisch unsichtbar. Dieser Artikel behandelt daher sowohl die rein visuelle Umsetzung mit Tailwind als auch die semantische Ebene, die bei den meisten Rating-Implementierungen im Web nachlässig behandelt wird.
2. Sterne mit Gradient-Fill als Füllstands-Basis
Der robusteste Ansatz für präzise Füllstände, auch bei krummen Werten wie 3.7, ist eine Gradient-Füllung statt einer reinen Klassen-Umschaltung zwischen gefüllt und leer. Jeder Stern besteht dabei aus zwei übereinandergelegten Symbolen: einem grauen Hintergrund-Stern als Basis und einem farbigen Vordergrund-Stern, dessen sichtbarer Anteil über einen linearen Gradient auf exakt den Prozentsatz begrenzt wird, der dem Füllstand entspricht. Bei einem Gesamtwert von 3.7 bekommen die ersten drei Sterne einen vollen Farbanteil, der vierte Stern einen Gradient-Stopp bei 70 Prozent und der fünfte bleibt komplett grau.
Technisch lässt sich das mit Tailwind über eine Kombination aus relative-Container, einem absolut positionierten Overlay-Stern und einer Inline-Style-Deklaration für den exakten Prozentwert umsetzen, da Tailwind selbst keine dynamischen Prozentwerte als Utility-Klasse anbietet. Die Basisklassen für Größe, Farbe und Positionierung kommen vollständig aus Tailwind, nur der variable Füllstand selbst wird als CSS-Custom-Property oder Inline-Style gesetzt, was diesen einen dynamischen Wert sauber von der ansonsten statischen Utility-Struktur trennt.
<div class="flex items-center gap-0.5" role="img" aria-label="3,7 von 5 Sternen">
<template x-for="i in 5" :key="i">
<span class="relative inline-block h-5 w-5" aria-hidden="true">
<!-- Hintergrund: immer grau, volle Sternform -->
<svg class="absolute inset-0 h-5 w-5 text-slate-200" viewBox="0 0 20 20" fill="currentColor">
<path d="M10 1.5l2.7 5.8 6.3.6-4.7 4.3 1.3 6.2L10 15.3l-5.6 3.1 1.3-6.2L1 7.9l6.3-.6z" />
</svg>
<!-- Vordergrund: gelb, per Clip-Path auf Füllstand begrenzt -->
<svg
class="absolute inset-0 h-5 w-5 text-amber-400"
viewBox="0 0 20 20"
fill="currentColor"
:style="`clip-path: inset(0 ${100 - Math.max(0, Math.min(100, (rating - (i - 1)) * 100))}% 0 0)`">
<path d="M10 1.5l2.7 5.8 6.3.6-4.7 4.3 1.3 6.2L10 15.3l-5.6 3.1 1.3-6.2L1 7.9l6.3-.6z" />
</svg>
</span>
</template>
</div>
3. Halbe Sterne: Clip-Path versus Gradient im Vergleich
Für den häufigen Sonderfall, in dem nur halbe Sterne vorkommen, also Bewertungen in 0.5er-Schritten statt beliebiger Kommazahlen, reicht oft ein einfacherer Ansatz mit genau drei Zuständen pro Stern: leer, halb und voll. Der halbe Zustand lässt sich entweder über clip-path: inset(0 50% 0 0) auf dem farbigen Vordergrund-Stern lösen, wie im vorherigen Codebeispiel mit fest 50 Prozent statt einem dynamischen Wert, oder über einen linearen Gradient direkt in der SVG-Definition mit zwei Farbstopps bei exakt 50 Prozent.
Der Clip-Path-Ansatz ist einfacher zu verstehen und zu debuggen, da er direkt mit sichtbaren Prozentwerten arbeitet, während die Gradient-Variante etwas mehr SVG-Vorwissen voraussetzt, dafür aber auch weichere Übergänge bei nicht-runden Prozentwerten ermöglicht, etwa bei den bereits erwähnten präzisen Durchschnittsbewertungen. Für die meisten Anwendungsfälle, in denen Nutzer nur ganze oder halbe Sterne vergeben können, reicht der Clip-Path-Ansatz vollkommen aus und bleibt deutlich wartungsfreundlicher, da keine SVG-Gradient-Definitionen separat gepflegt werden müssen.
4. Interaktive Hover-Vorschau bei der Bewertungs-Eingabe
Bei der editierbaren Variante muss jeder Stern einzeln auf Hover reagieren und dabei eine Vorschau anzeigen, wie die Bewertung aussehen würde, wenn der Nutzer jetzt an dieser Position klickt. Das bedeutet, dass alle Sterne bis zur Hover-Position farbig gefüllt dargestellt werden, während die tatsächlich bereits gespeicherte Bewertung erst nach Verlassen des gesamten Rating-Bereichs wieder sichtbar wird. Mit Alpine.js lässt sich das über eine separate hoverIndex-Variable lösen, die getrennt von der eigentlichen rating-Variable geführt wird und beim mouseleave auf dem Container auf null zurückgesetzt wird.
Wichtig ist, dass die Hover-Vorschau visuell klar als vorläufig erkennbar bleibt und sich nicht komplett wie die finale Auswahl anfühlt, meist durch eine minimal reduzierte Deckkraft oder einen leichten Skalierungs-Effekt auf dem gehoverten Stern selbst. Der eigentliche Klick setzt dann den finalen Wert, und ein kurzer visueller Bestätigungs-Effekt, etwa ein kurzes Aufblitzen oder eine kleine Skalierungs-Animation, gibt dem Nutzer Feedback, dass die Bewertung tatsächlich übernommen wurde und nicht nur vorübergehend als Hover-Zustand sichtbar ist.
5. Read-only-Anzeige versus editierbare Eingabe
Die read-only Variante, wie sie typischerweise unter einem Produktnamen als Durchschnittsbewertung erscheint, braucht keinerlei Hover- oder Klick-Handler und sollte auch keinen Cursor-Pointer anzeigen, der fälschlich Interaktivität suggeriert. Hier reicht die reine Gradient- oder Clip-Path-Darstellung aus dem vorherigen Abschnitt vollständig aus, ergänzt um einen begleitenden Text mit dem exakten Zahlenwert und der Anzahl der Bewertungen, etwa '4,3 von 5 (128 Bewertungen)', da die reine visuelle Darstellung allein selten präzise genug abgelesen werden kann.
Die editierbare Variante dagegen braucht zwingend einen cursor-pointer auf jedem einzelnen Stern, eine sichtbare Hover-Vorschau wie im vorherigen Abschnitt beschrieben, und in der Regel auch eine Möglichkeit, die Bewertung wieder zu löschen, etwa durch erneutes Klicken auf den bereits aktiven letzten Stern. Beide Varianten sollten sich im Code klar durch eine Prop oder ein Flag wie readonly unterscheiden lassen, damit dieselbe Basis-Komponente für beide Fälle wiederverwendet werden kann, statt zwei komplett getrennte Implementierungen zu pflegen.
6. Barrierefreiheit: aria-label statt reiner visueller Darstellung
Da Sterne rein dekorative SVG-Grafiken sind, tragen sie für sich genommen keine für Screenreader zugängliche Information, selbst wenn ihr Füllstand visuell absolut korrekt dargestellt wird. Die gesamte Sterne-Gruppe braucht daher einen umschließenden Container mit role="img" und einem aria-label, das den exakten Wert in Textform enthält, etwa 'aria-label="3,7 von 5 Sternen"', während jeder einzelne Stern innerhalb der Gruppe aria-hidden="true" bekommt, damit Screenreader nicht fälschlich fünf einzelne, bedeutungslose Grafiken vorlesen.
Bei der editierbaren Variante reicht ein reiner role="img" nicht mehr aus, da die Komponente jetzt interaktiv ist. Hier bietet sich eine semantische Radio-Gruppe an, bei der jeder Stern als role="radio" innerhalb einer role="radiogroup" fungiert, mit einem eigenen aria-label pro Stern wie 'aria-label="4 Sterne vergeben"'. Diese Struktur erlaubt zusätzlich eine native Tastatur-Navigation mit den Pfeiltasten zwischen den einzelnen Bewertungsstufen, was bei einer reinen Klick-Interaktion ohne semantische Struktur komplett fehlen würde.
7. Größenvarianten für unterschiedliche Kontexte
Sternebewertungen tauchen in sehr unterschiedlichen Kontexten auf, von einer kompakten Anzeige in einer Produktliste bis zu einer prominenten Eingabe-Komponente auf einer Bewertungs-Detailseite, und brauchen entsprechend unterschiedliche Größen. Mit Tailwind lässt sich das sauber über ein kleines Set fester Größenklassen lösen, etwa h-3.5 w-3.5 für die kompakte Listenansicht, h-5 w-5 als Standardgröße und h-8 w-8 für die große, interaktive Eingabe-Variante, statt beliebige Zwischenwerte zuzulassen, die die visuelle Konsistenz der gesamten Anwendung untergraben würden.
Bei der kompakten Größe lohnt es sich zusätzlich, den Abstand zwischen den einzelnen Sternen zu reduzieren, etwa von gap-0.5 auf einen noch engeren Wert, da fünf Sterne mit vollem Standardabstand in einer engen Produktliste schnell zu viel horizontalen Platz beanspruchen. Bei der großen, interaktiven Variante dagegen darf der Abstand ruhig großzügiger ausfallen, da hier jeder einzelne Stern ein eigenständiges, gut treffbares Klick-Ziel darstellen muss, besonders auf Touch-Geräten.
8. Farbthemen und Dark-Mode-Anpassung
Die klassische Sternfarbe ist ein warmes Gelb oder Amber, meist text-amber-400, das sich auf hellem Hintergrund gut vom neutralen Grau des unausgefüllten Sterns abhebt. Im Dark Mode muss diese Farbe angepasst werden, da ein zu gedämpftes Amber auf dunklem Hintergrund an Kontrast verliert, während der graue Hintergrund-Stern im Dark Mode ebenfalls von einem hellen Grau auf einen dunkleren Grauton wie dark:text-slate-600 wechseln sollte, um nicht selbst wie ein aktiver Stern zu wirken.
Für Anwendungen mit einem eigenen Marken-Farbschema kann die Sternfarbe grundsätzlich durch die primäre Akzentfarbe ersetzt werden, wichtig ist dabei nur, dass der Kontrast zwischen gefülltem und leerem Zustand in beiden Farbmodi deutlich genug bleibt, idealerweise mit einem Kontrastverhältnis von mindestens 3:1 zwischen den beiden Zuständen. Ein zu subtiler Unterschied zwischen Voll- und Leerzustand macht die Bewertung schwer ablesbar, besonders bei kleiner Darstellungsgröße in Produktlisten.
9. SVG-Icons versus Icon-Fonts für Sterne
Für die Sternform selbst bieten sich zwei technische Ansätze an: Inline-SVG-Pfade wie im Codebeispiel oben, oder eine Icon-Font mit Sternzeichen, deren Füllung über die CSS-Farbe des Font-Zeichens gesteuert wird. Inline-SVG hat den klaren Vorteil, dass sich der Füllstand präzise per Clip-Path oder Gradient steuern lässt, während eine Icon-Font für halbe oder krumme Füllstände auf einen zweiten, überlagerten Font-Charakter mit Clip-Path angewiesen ist, was in der Praxis kaum einfacher ist als die SVG-Variante.
Zusätzlich vermeidet Inline-SVG das bekannte Problem des kurzen Aufblitzens ungestylter Zeichen, das bei extern geladenen Icon-Fonts auftreten kann, bevor die Font-Datei vollständig geladen ist. Da Sterne meist above-the-fold und damit sofort sichtbar sind, sollte dieses Aufblitzen unbedingt vermieden werden, weshalb Inline-SVG für Rating-Komponenten in aller Regel die robustere und empfehlenswertere Wahl gegenüber Icon-Fonts darstellt.
| Variante | Größe (Tailwind) | Interaktion | Aria-Rolle |
|---|---|---|---|
| Kompakt (Liste) | h-3.5 w-3.5 | Keine, rein lesend | role="img" |
| Standard (read-only) | h-5 w-5 | Keine, rein lesend | role="img" |
| Editierbar (Formular) | h-8 w-8 | Hover-Vorschau + Klick | role="radiogroup" |
| Kompakt editierbar | h-5 w-5 | Klick ohne Hover-Vorschau | role="radiogroup" |
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
Rating- und Sternebewertung-Komponenten mit Tailwind: Das Wichtigste auf einen Blick
Füllstand
Gradient oder Clip-Path für präzise Prozentwerte, nicht nur grobe gefüllt/leer-Umschaltung.
Hover-Vorschau
Separate Hover-Variable getrennt vom gespeicherten Wert, mit klarer visueller Unterscheidung.
Barrierefreiheit
role=img mit aria-label für read-only, role=radiogroup mit Tastaturnavigation für editierbar.
Technik
Inline-SVG statt Icon-Font, wegen präziser Clip-Path-Steuerung und ohne Füllungs-Aufblitzen.