Chuck Norris hat ein „Sie haben gewonnen“-Banner angeklickt. Und er hat gewonnen!

7.11.09

Ente Ente Ente – Folgen in CSS

CSS3 bringt eine ganze Palette neuer Selektierungsmöglichkeiten mit. Beinahe uneingeschränkt kann man sich damit durch den DOM-Wald hangeln und fast jedes noch so unbestimmte Element auswählen. Einen großen Beitrag zu dieser Erleichterung tragen die neuen Structural pseudo-classes bei. Während man bei der Verwendung von first-child und last-child noch keine größeren Probleme haben dürfte, gestaltet sich der Gebrauch von nth-child() und nth-of-type() etc. schwieriger, was schon beim Namen beginnt.

Der Name: Was ist „nth“?

Im Mathematikunterricht hat jeder schon einmal etwas von dem „n-ten Element“ gehört und sich dabei gefragt, was Enten auf einmal mit Mathe zu tun haben.

Spätestens nach dem zweiten „WTF?“, das durch den Klassenraum schallte, erklärte der Lehrende, dass es sich dabei um eine allgemeine Form für „Das erste, zweite, dritte, … Element“ handelt.

Dieses allgemeine „n-te“ findet sich im Englischen als „nth“ wieder (4th, 5th, 6th, … nth). Der Selektor nth-child() wählt jedes Element aus, auf das die nachfolgenden Bedingung passt. Diese Bedingung steht in Klammern.

Die Bedingung in den Klammern

Und wieder mache ich zuerst einen Ausflug in die Mathematik. In den Klammern steht nämlich eine explizite Folgenvorschrift der Form „an+b“. Das n ist hier die praktische Variable, a und b werden durch ganzzahlige Werte ersetzt.

Ein Beispiel für die Funktionsweise:

<!-- HTML: Eine Liste -->
<ul id="vater">
	<li>Brigitte</li>
	<li>Joachim</li>
	<li>Maybritt</li>
	<li>Ilse</li>
	<li>Klaus</li>
	<li>Orlof</li>
	<li>Bruno</li>
</ul>

Und das CSS:

/* CSS */
#vater :nth-child(2n+0) {
	background: red;
}

Hier haben wir es mit einem Vater zu tun, der sieben Kinder hat. Die Pseudo-Klasse nth-child(2n+0) wählt nun all’ diejenigen Elemente aus, die der Folgenvorschrift 2n+0 entsprechen und einen gemeinsamen übergeordneten Verwandten haben.

Zur Veranschaulichung hier ein Auszug einer Wertetabelle:

1 2 3 4 5 n
2 4 6 8 10 2n+0

Es werden also Joachim (2. Kindelement), Ilse (4. Kindelement) und Orlof (6. Kindelement) ausgewählt und mit einem roten Hintergrund versehen. Oder eben allgemein: Es wird jedes „2n+0“-te Element ausgewählt, für alle n∈ℕ (n ist Element der Natürlichen Zahlenmenge).

Den Ausdruck „2n+0“ könnte man auch als „2n-0“ schreiben. Da die Null aber ohnehin keine Auswirkung hat, kann man diese auch ganz weglassen. Die Vorschrift „2n“ hat aber auch einen reservierten Alias: even. So kann man mittels :nth-child(even) die gleiche Selektierung erreichen. Das Gegenstück dazu wäre „odd“, welches alle Kindelemente mit ungeradem Index auswählen würde und 2n+1 entspräche.

Anstatt die Pseudo-Klasse :first-child zu benutzen, kann man das gleiche mittels nth-child und dem Ausdruck :nth-child(1) erreichen, denn das Angeben einer variablen Komponente n ist optional, was daher rührt, dass :nth-child(0n+1) den gleichen Effekt hätte, aber weniger übersichtlich aussähe.

Man kann mit dem Selektor auch mehrere Elemente auswählen. Der Ausdruck :nth-child(-n+4) wählt z.B. die ersten vier Elemente aus, der Ausdruck :nth-child(n-4) alle außer den ersten Vieren*, denn als positive Indexes lassen sich hier nur 4, 3, 2 und 1 errechnen. Negative Indexes bzw. den nullten Index gibt es nicht.

*Anmerkung: Denkfehler des Autors, danke an Tim!

nth-last-child

Die Pseudo-Klasse :nth-last-child() ist das Gegenstück zum obigen :nth-child(). Der einzige Unterschied ist, dass die Elemente nicht vom ersten Element an durchgezählt werden, sondern vom letzten. nth-last-child(2n) wählt das vorletzte Element, das viertletzte, sechstletzte und so weiter.

nth-of-type und nth-last-of-type

Hierbei werden nicht die Kinder durchgezählt, sondern alle Elemente, die vor dem Doppelpunkt stehen. Und zwar bezogen auf das gesamte Dokument. Ein Beispiel:

<!-- HTML -->
<div>
	<img title="erstes Bild im Dokument" />
	<img title="zweites Bild im Dokument" />
	<div>
		<img title="drittes Bild im Dokument" />
	</div>
</div>
<img title="viertes Bild im Dokument" />

Der Ausdruck img:nth-of-type(2n+1) würde demnach das erste und dritte Bild selektieren. Kindlichkeit wird nicht beachtet.

nth-last-of-type sollte mit der Kenntnis der Funktionsweise von nth-last-child selbsterklärend sein.

Die Browserfrage

Die Browsersituation ist übersichtlich aber unschön. Weder Firefox 3.0 noch der Internet Explorer 8 verstehen überhaupt eine der obigen Regeln. Der FF3.0 liegt ja zum Glück im Sterbebett darnieder; ob man beim IE9 auf umfassenden Structural pseudo-classes-Support hoffen kann, ist aber ungewiss.

Bei Konstrukten wie :nth-child(4) kann man sich mit dem Adjacent Sibling Selector (+) und :first-child zumindest teilweise helfen. Möchte man z.B. das vierte li einer Liste anwählen, verhilft ein kompliziertes li:first-child + li + li + li zum Glück.

Kommentare [2]

Tim am 8.11.2009 um 14:21

… der Ausdruck :nth-child(n-4) alle außer den ersten Vieren.

Das ist eine Ente. Wenn man bei diesem Ausdruck eine Wertetabelle anlegt, dann sind zwar für n=0 bis n=4 die Werte ≤ 0, für n=5 ist das Ergebnis 1, für n=6 ⇒ 2 usw. Das bedeutet, für jeden Wert > 0 gibt es ein n ≥ 0, bei dem die Gleichung stimmt. Deswegen würde ein :nth-child(n-4) alle Kinder selektieren.

Der richtige Ausdruck um alle Elemente ab dem Fünften auszuwählen ist deshalb

:nth-child(n+5)

Markus am 8.11.2009 um 14:50

Mist, falsch herum gedacht, stimmt. Der nächste Beitrag, der hier erscheint wird das noch mal etwas kritischer betrachten. Aber danke für den Hinweis, werde das einarbeiten.

Kommentar verfassen

Textile-Hilfe

  • *stark*
  • _betont_
  • "Link":http://url.com/
  • bq. Zitatkasten
  • bc. Code-Block
Der Kommentar kann erst abgeschickt werden, wenn man mindestens einmal die Vorschaufunktion aktiviert hat.

Flattr

Blogrolle

Podroll

Soziale Netzwerke

Twitroll