Star-Rating mit CSS

Überall dort, wo Beiträge, Dateien oder Videos bewertet werden können, hat man meist die Möglichkeit, in mehreren Stufen zu bewerten (beispielsweise fünf). Nicht selten werden diese grafisch als Sterne dargestellt – je mehr dieser Sterne farbig sind, desto höher die Bewertung. Beispielhaft sei hier das Rating der Videos auf Youtube genannt, das sich direkt unter den Videos befindet. Ein solches Star-Rating (mit Kreisen statt Sternen) werden wir in diesem kleinen Tutorial erschaffen, allerdings komplett ohne JavaScript, nur mit ein bisschen HTML und CSS. Allerdings sparen wir uns die eigentliche Funktionalität dahinter und konzentrieren uns nur auf die Darstellung, die in der Demo des Endergebnisses zu sehen ist.

Den Anfang macht das HTML-Grundgerüst, das hier aufs nötigste reduziert wurde. Ein div-Element kapselt dabei die Bewertung, während fünf Links die einzelnen Bewertungen darstellen – diese können später auf das Rating-Script verlinken oder eine JavaScript-Funktion aufrufen. Das soll aber nicht Gegenstand dieses Tutorials sein.

<div class="rating">
	<a href="#" class="rate1">1</a>
	<a href="#" class="rate2">2</a>
	<a href="#" class="rate3">3</a>
	<a href="#" class="rate4">4</a>
	<a href="#" class="rate5">5</a>
</div>

Die Ziffern in den Links stellen die Bewertung dar, eine eins ist dabei das schlechteste, fünf die beste Bewertung. Ohne CSS sieht das ganze noch recht trostlos aus, da die Links alle einfach hintereinander aufgeführt sind – den Anblick können wir uns sparen. Kommen wir also zu unserem Plan: Die Bewertung soll im ursprünglichen Zustand fünf Kreise anzeigen, die sich nur schwach vom Hintergrund abheben. Fährt man mit der Maus über einen dieser Kreise, so wird dieser und alle links davon liegenden farbig hervorgehoben und damit wird die Bewertung dargestellt. Die Ziffern selber sollen nicht sichtbar sein. Bevor wir uns aber Gedanken um die Grafik machen, vereinfachen wir die Darstellung, indem wir einfach nur unterschiedliche Hintergrundfarben wählen, um die Zustände anzuzeigen.

Wir konzentrieren uns also erstmal auf das Konzept. Die Idee dahinter ist, dass die Links übereinander liegen und sich damit teilweise verdecken. Der erste Link ist gerade so breit, dass ein Kreis auf ihm Platz hätte, der letzte nimmt die volle Breite ein (fünf Kreise) und der Rest liegt dazwischen. Gleichzeitig sind die Links der Breite nach sortiert, so dass der erste (und schmalste) ganz oben auf liegt, während der letzte auch der unterste ist. Da dieser aber auch der breiteste ist, gibt es einen schmalen Bereich, der anklickbar ist. Zur Verdeutlichung des eben Beschriebenen habe ich ein kleines Bild gebastelt:

Schema des RatingsSchematische Darstellung der Link-Ebenen

Der CSS-Code, der dafür nötig ist, hält sich in Grenzen:

.rating {
	position: relative;
	width: 100px;
	height: 20px;
	border: 1px solid #ccc;
	background: #eee;
}

.rating a {
	position: absolute;
	height: 20px;
	text-indent: -9000px;
}

.rating a:hover {
	background: #cdf;
}

.rating .rate1 {
	width: 20px;
	z-index: 5;
}

.rating .rate2 {
	width: 40px;
	z-index: 4;
}

.rating .rate3 {
	width: 60px;
	z-index: 3;
}

.rating .rate4 {
	width: 80px;
	z-index: 2;
}

.rating .rate5 {
	width: 100px;
	z-index: 1;
}

Zuerst wird die Breite und Höhe des gesamten Ratings festgelegt. Pro Kreis ist ein Platz von 20 x 20 Pixeln vorgesehen, so dass die Gesamtbewertung 100 Pixel breit ist. Durch Rahmen und Hintergrundfarbe wird sie erstmal sichtbar gemacht. Außerdem wird eine relative Positionierung angegeben, denn damit beziehen sich absolut positionierte Elemente im Inneren auf das äußere div und nicht auf das Browserfenster. Damit die Links nun auch wirklich übereinander liegen und sich verdecken, müssen sie absolut positioniert werden. Außerdem bekommen sie noch eine Höhe und der enthaltene Text wird weit nach links aus dem sichtbaren Bereich hinausgeschoben, damit die Zahlen später nicht im Weg sind. Beim Überfahren mit der Maus soll sich einfach nur der Hintergrund des jeweiligen Links ändern.

Anschließend wird noch jedem der fünf Links ein eigener Style gegeben. Durch die absolute Positionierung befinden sie sich alle am linken Rand des Ratings, da wir nichts anderes angeben. Die Breite bestimmt, wie weit der Link nach rechts ragt, der z-index bestimmt die Ebene – je niedriger, desto weiter unten (auf der z-Achse) ist das Element. Beim letzten Link ist also ganz rechts ein 20 x 20 Pixel großer Bereich anklickbar, die restlichen 80 Pixel werden von den darüber liegenden Links verdeckt. So ändert sich der Hintergrund des gesamten Ratings, obwohl der Link für den Anwender scheinbar nur sehr schmal ist. Das bisherige Ergebnis zeigt, dass das Prinzip funktioniert.

Nun wollen wir auch die Grafik ins Spiel bringen. Diese ist recht klein – nämlich so breit, wie ein Link, dafür doppelt so hoch, da sie beide Zustände des Kreises beinhaltet. Oben der farblose Kreis, unten der hervorgehobene:

Rating-GrafikRating-Grafik

Nun verwenden wir statt der Hintergrundfarbe diese Grafik, die zu ändernden Stellen habe ich hier nur hervorgehoben, der Rest stimmt mit dem eben gezeigten CSS-Code überein:

.rating {
	position: relative;
	width: 100px;
	height: 20px;
	border: 1px solid #ccc;
	background: url(circle.png) top left repeat-x;
}

.rating a {
	position: absolute;
	height: 20px;
	text-indent: -9000px;
}

.rating a:hover {
	background: url(circle.png) bottom left repeat-x;
}

.rating .rate1 {
	width: 20px;
	z-index: 5;
}

.rating .rate2 {
	width: 40px;
	z-index: 4;
}

.rating .rate3 {
	width: 60px;
	z-index: 3;
}

.rating .rate4 {
	width: 80px;
	z-index: 2;
}

.rating .rate5 {
	width: 100px;
	z-index: 1;
}

Der Hintergrund ändert sich dadurch, dass die selbe Grafik verschoben angezeigt wird. Dadurch wird vermieden, dass erst beim Überfahren mit der Maus ein weiteres Bild mit dem anderen Zustand geladen werden muss und dieses stattdessen sofort erscheint. Das Ergebnis lässt sich schon sehen, aber wir wollen mehr. Neben der Anzeige der Kreise wollen wir jetzt auch noch einen kurzen beschreibenden Text anzeigen, der dem Nutzer vermitteln soll, was die Bewertung, die er abgibt, eigentlich bedeutet. In unserem Beispiel sollen das in aufsteigender Reihenfolge die Texte „Mangelhaft“, „Ausreichend“, „Befriedigend“, „Gut“ und „Sehr gut“ sein. In unserem HTML-Code werden also die Ziffern durch die entsprechenden Texte ausgetauscht:

<div class="rating">
	<a href="#" class="rate1"><span>Mangelhaft</span></a>
	<a href="#" class="rate2"><span>Ausreichend</span></a>
	<a href="#" class="rate3"><span>Befriedigend</span></a>
	<a href="#" class="rate4"><span>Gut</span></a>
	<a href="#" class="rate5"><span>Sehr gut</span></a>
</div>

Die zusätzliche Kapselung in das span-Element ist in unserem Fall nötig, um den erhofften Effekt zu erzielen. Dieses Element wird, ebenfalls mittels absoluter Positionierung, nach rechts außerhalb der Links verschoben. Hier wieder das komplette Beispiel mit den hervorgehobenen nötigen Änderungen:

.rating {
	position: relative;
	width: 100px;
	height: 20px;
	border: 1px solid #ccc;
	background: url(circle.gif) top left repeat-x;
}

.rating a {
	position: absolute;
	height: 20px;
	text-decoration: none;
}

.rating a span {
	position: absolute;
	left: 105px;
	line-height: 20px;
	font-size: 12px;
	color: #999;
	white-space: nowrap;
	visibility: hidden;
}

.rating a:hover {
	background: url(circle.gif) bottom left repeat-x;
}

.rating a:hover span {
	visibility: visible;
}

.rating .rate1 {
	width: 20px;
	z-index: 5;
}

.rating .rate2 {
	width: 40px;
	z-index: 4;
}

.rating .rate3 {
	width: 60px;
	z-index: 3;
}

.rating .rate4 {
	width: 80px;
	z-index: 2;
}

.rating .rate5 {
	width: 100px;
	z-index: 1;
}

Im ursprünglichen Zustand ist der Text unsichtbar, erst beim Überfahren mit der Maus ist er zu sehen. Durch die eingestellte Zeilenhöhe wird der Text passend zu den Kreisen in der Höhe zentriert und das white-space: nowrap; sorgt dafür, dass Worte nicht umgebrochen werden. Ohne diese Anweisung stünde bei der besten Bewertung dank Zeilenumbruch das „gut“ unter dem „sehr“. Damit haben wir uns nun auch das Endergebnis erarbeitet und sind fertig. Die fertigen Beispiele könnt ihr euch als Zip-Archiv herunterladen.

Tags: ,

2 Antworten

  1. dirk says:

    danke dir 🙂

  2. ex-ratt says:

    Keine Ursache 😉
    Hab übrigens die Bilder wieder drin, die müssen mir letztens bei einer Umräumaktion mal abhanden gekommen sein.

Hinterlasse eine Antwort