Zählen mit CSS

Wäre es nicht fantastisch, eine Liste oder ein Menü in Abhängigkeit von der Anzahl der enthaltenen Elmente behandeln zu können? Und das nur mit CSS? Wenn man sagen könnte: „Wenn diese Liste weniger als 5 Listenelemente hat, dann setze bei all diesen Elementen das Attribut display auf „inline-block“. Oder: „Wenn dieses Menü mehr als 7 Elemente hat, verringere die Schriftgröße aller Menüpunkte auf 10px. Die schlechte Nachricht zuerst: CSS kann von Haus aus nicht zählen. Die gute Nachricht: Es funktioniert trotzdem. Jetzt. Mit standard-CSS. Keine Prototypen, keine Browserpräfixe und keine wagen Spezifikationen aus der Zukunft. Hier lesen Sie, wie genau das funktioniert.

Träumt CSS-Code von elektrischen Schafen?

Die Antwort ist: Nein. CSS kann nicht zählen. Abgesehen von den Pseudo-Selectoren :only-child und :only-of-type, die nur die einzigen Kind-Elemente bzw. einzigen Elemente eines Typs selektieren, gibt es, abgesehen von der hier vorgestellte Methode, aktuell keine Möglichkeit mit reinem CSS Elemente zu zählen. Der Retter in der Not ist der Pseudo-Selektor nth-last-child(). Schauen wir uns zunächst an, was dieser überhaupt macht.

Anzahl N

:nth-last-child() akzeptiert als Parameter den Zähler n. Nutzt man diesen, so kann man vom letzten Kind-Element aus zurückzählen. Beispielsweise matched li:nth-last-child(10) das Zehnte vom letzten li-Element entfernte Element. Wenn es also 15 li-Elemente gibt, wird hier das Element Nummer 5 ausgewählt. Das allein hilft uns aber noch nicht weiter. Wir brauchen zusätzlich noch den Pseudoselektor :first-child. Verbinden wir nun beides zusammen, erhalten wir:

li:nth-last-child(10):first-child {
/* Styling für das erste Element, wenn es genau 10 Elemente gibt */
}

Auf ziemlich komplizierte Art und Weise wissen wir damit nun, wieviele Elemente vorhanden sind. Die Bedigung ist nämlich nur wahr, wenn das erste Element auch gleichzeitig das Zehnte von hinten ist. Gibt es also genau 10 Elemente, greift nun der CSS Code in den geschweiften Klammern. Wie kann man nun aber alle diese Elemente verändern, wenn es genau 10 Elemente gibt ? Ganz einfach: mit dem Geschwister-Operator ~.

Vererbung an Geschwister

li:nth-last-child(10):first-child ~ li {
/* Styling für alle li-Elemente, nach dem ersten li-Element, wenn es genau 10 Elemente gibt */
}

und um wirklich alle Elemente zu matchen:

li:nth-last-child(10):first-child,
li:nth-last-child(10):first-child ~ li {
/* Styling für alle li-Elemente, nach dem ersten li-Element INKLUSIVE dem ersten li-Element, wenn es genau 10 Elemente gibt */
}

Dies hilft uns schon sehr weiter. Was ist nun aber, wenn wir diese Elemente nur verändern möchten, wenn 10 oder mehr als 10 Elemente gibt ? Auch das geht. Jetzt wird es allerdings ein wenig knifflig.

Größer gleich

Um nur bestimmte Elemente zu behandeln, wenn es insgesamt z.B. mehr als 10 Elemente gibt, dedarf es eines weiteren Tricks. Der Pseudoselektor :nth-last-child() akzeptiert nämlich auch die (n+x) Syntax. Dies kommt uns sehr gelegen, weil wir damit nun eine bestimmte Anzahl von Elementen von hinten aus gezählt ausschließen können. Schreiben wir also:

li:nth-last-child(n+8) {
/* Styling für alle li-Elemente, die vor dem achtletzten Element von hinten gezählt vorkommen */
}

Die Erklärung dafür ist einfach: Angenommen es gibt insgesamt 10 li-Elemente und wir verwenden oben genannten Selektor. Dann gilt die Bedingung für die ersten drei Elemente, da diese nur ab- und einschließlich dem achten von hinten aus gezählten Element wahr ist. Es werden also auch alle Elemente davor gematched. Gäbe es nur insgesamt 9 Elemente, wären nur die ersten zwei Elemente betroffen, bei 8 Elementen, nur das Erste. Wir wollen allerdings alle Elemente stylen, und nicht nur die ersten. Sie ahnen es schon: Wir greifen erneut auf unseren Geschwister-Operator ~ zurück:

li:nth-last-child(n+10),
li:nth-last-child(n+10) ~ li  {
/* Styling für alle li-Elemente, wenn es 10 oder mehr Elemente gibt */
}

Damit können wir nun allen Elementen Eigenschaften zuweisen, die nur dann aktiv werden, wenn es mindestens- oder mehr als die festgelegte Anzahl von Elementen gibt. Das Gleiche geht natürlich auch anders herum.

Kleiner gleich

Wie kehrt man das ganze nun aber um, damit man alle Elemente behandeln kann, wenn es weniger als eine bestimmte Anzahl von Elementen gibt ? So wie man es auch in der Mathematik macht: Man kehrt das Vorzeichen um. Zusätzlich hängen wir noch ein :first-child an.

li:nth-last-child(-n+10):first-child,
li:nth-last-child(-n+10):first-child ~ li  {
/* Styling für alle li-Elemente, wenn es 10 oder weniger Elemente gibt */
}

In diesem Fall ändert man die Richtung der Selektierung. Anstatt vom sechsten Element von hinten zum Anfang zu zählen, wird nun vom sechsten Element von hinten zum Ende hin gezählt. Da wir aber alle Elemente verändern wollen, müssen wir hier noch :first-child bzw. :first-child ~ li anhängen, damit auch wieder vom Anfang an alle Elemente behandelt werden können.

Wenn Sie bis hier hin gelesen haben, dürften Sie nun ungefähr verstehen, wie die Zählung mit :nth-last-child() funktioniert. Allerdings können Sie für alle diese Beispiele auch :nth-last-of-type() benutzen. Es kommt darauf an, für welchen Anwendungsfall Sie die Bedingungen schreiben. Beide Arten von Queries haben Ihre Vor- und Nachteile. :nth-last-of-type() ist z.B. dann sinnvoll, wenn es unter einem Elternelement Kinderelemente verschiedenen Typs gibt und man nur diese zählen will. :nth-last-child() würde in diesem Fall alle Kind-Elemente zählen.

Browser-Support

Die vorgestellte Methode funktioniert in so gut wie allen modernen Browsern und dem Internet Explorer beginnend mit Version 9. Für ältere Versionen müsste in diesem Fall ein JavaScript polyfill verwendet werden. Da es sich hier aber um reguläres standard-CSS handelt, kann man dieses bedenkenlos in vollem Umfang benutzen.

Auf dieser Seite wurde ein Tool zum Testen dieser Methode eingerichtet. Wenn Sie möchten, können Sie Ihre sogenannten Quantity Queries dort ausprobieren.

Was Sie letztendlich mit dem CSS-Zähler anfangen, bleibt Ihnen überlassen. Sie könnten, wie bereits am Anfang erwähnt, ein horizontales Menü, je nach Anzahl der Elemente anders behandeln oder eine Matrix anzeigen lassen, bei der sich jedes Element verkleinert, wenn mehr Elemente hinzugefügt werden. Die Möglichkeiten sind hier unbegrenzt.

Wir wünschen Ihnen viel Spaß beim Ausprobieren.

0 Kommentare

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert