HTML/Tutorials/Listen/Hybride Nummerierung

Aus SELFHTML-Wiki
< HTML‎ | Tutorials‎ | Listen(Weitergeleitet von Counters())
Wechseln zu: Navigation, Suche

Listen sind ein praktisches und oft verwendetes Mittel zur Darstellung von Informationen, wie z. B. Inhaltsverzeichnissen. Mit Hilfe von HTML ist es zwar möglich, auch die Nummerierung von Listen zu bestimmen, jedoch sind die Grenzen dabei bald erreicht, wenn es um eine hybride, also um eine gemischte Art der Nummerierung geht, bei der verschiedene Aufzählungsformate gemischt werden müssen.

CSS schafft hier Abhilfe durch die Möglichkeit, eigene Zähler zu definieren, zu verändern und sie mit der counter()-Funktion in automatisch generierte Inhalte einzufügen. Die Erstellung solcher Zähler ist Teil des Seitenlayouts, so dass sie jedesmal, wenn die Seite neu aufgebaut wird, mit aktualisiert werden.

Was ist ein Zähler

Ein CSS-Zähler ist etwas ähnliches wie eine Variable mit ganzzahligem Wert. Sie können ihn erstellen, setzen, ändern und abrufen. Und er besitzt einen Gültigkeitsbereich. Ausdrücklich erstellen müssen Sie einen Zähler nicht. Wenn Sie das unterlassen, erstellt CSS ihn automatisch, sobald er das erste Mal verwendet werden soll, und setzt ihn auf 0.

Zähler sind immer einem HTML Element zugeordnet. Wenn Sie einen Zähler erstellen – oder CSS ihn automatisch erstellt – gehört er zu dem Element, in dem er erstellt wurde, und ist dann für dessen Kindelemente sowie für seine nachfolgenden Geschwisterelemente und deren Kindelemente verfügbar.

Um einen Zähler explizit zu erstellen, verwenden Sie die Eigenschaft counter-reset. Dahinter notieren Sie den Namen, den der Zähler tragen soll, und optional den Wert, den er bekommen soll.

Definieren eines Zählers
h1 {
   counter-reset: count2 0;
}

Der Name muss ein gültiger CSS-Name sein. Der Wert muss eine Ganzzahl sein und ist optional. Wenn Sie ihn weglassen, wird der Zähler auf 0 gesetzt.

Wenn Sie auf einem Element mehr als einen Zähler erzeugen wollen, geben Sie hinter counter-reset mehrere Name-Wert Paare an. Verwenden Sie nicht mehrere counter-reset Angaben, wie bei allen CSS-Eigenschaften würde nur die letzte beachtet werden.

Mehrere Zähler definieren
h1 {
   counter-reset: count2 0 gruppe 3;
}

Einfache Zähler

Wie verändert man einen Zähler

Sie können Zähler um einen bestimmten Wert verändern oder (seit 2020) auch auf einen neuen Wert setzen. Dazu verwenden Sie die CSS-Eigenschaften counter-increment oder counter-set:

Verändern eines Zählers
h2 {
   counter-increment: count2 1;
}

Die Angabe eines Wertes bei counter-increment ist ebenfalls optional. Wenn Sie ihn weglassen, verwendet CSS die 1. Genau wie bei counter-reset gilt: Wollen Sie mehrere Zähler verändern, müssen Sie alle Änderungen in einer counter-increment-Eigenschaft gemeinsam angeben.

Im vorherigen Abschnitt haben wir in <h1>-Überschriften den Zähler count2 auf 0 gesetzt. Nun wird er für <h2> Überschriften um 1 erhöht. Die Wirkung ist, dass mit jeder <h1>-Überschrift die Zählung der <h2>-Überschriften aufs Neue beginnt.

Anstatt einen Zähler um einen bestimmten Wert zu verändern, können Sie ihm auch einen neuen Wert zuweisen. Dazu dient die Eigenschaft counter-set:

Setzen des Wertes für einen Zähler
h1 {
   counter-set: count2 0;
}

Die Eigenschaften counter-reset und counter-set scheinen auf den ersten Blick das Gleiche zu tun. Auf die Unterschiede gehen wir ein, wenn wir Gültigkeitsbereiche und Vererbung von Zählern diskutieren.

Wie zeige ich einen Zählerwert an

Das haben Sie sich bestimmt schon längst gefragt. Für die Anzeige eines Zählerinhalts nutzt CSS die content-Eigenschaft, die in Pseudoelementen wie ::before, ::after oder ::marker verwendet werden kann, und darin die CSS-Funktion counter() (engl. für Zähler), um den Inhalt eines Zählers abzurufen. Auf diese Weise können Sie überall den Wert, den ein Zähler an dieser Stelle hat, darstellen und auch formatieren.

Syntax counter(name, <list-style-type>)

  • name: Der Name des Zählers, dessen Wert auszugeben ist.
  • list-style-type ist ein optionaler Parameter, der die Darstellung der Durchnummerierung festlegt.

Für die Darstellung sind alle Stiltypen verwendbar, sie Sie auch bei geordneten Listen nutzen können. CSS verwendet intern Ganzzahlen, aber für die Ausgabe können Sie wie bei einer Listennummerierung auch römische Zahlen, Buchstaben oder auch selbst definierte Symbollisten verwenden.

Überschriftennummerierung ansehen …
<h1>Hauptüberschrift</h1>
<h2>Unterüberschrift</h2>
<h2>Unterüberschrift</h2>
<h1>Hauptüberschrift</h1>
<h2>Unterüberschrift</h2>
body {
   counter-reset: count1 0 count2 0;
h1 {
   counter-increment: count1;
   counter-set: count2 0;
}
h1::before {
   content: counter(count1) ' ';
}
h2 {
   counter-increment: count2;
}
h2::before {
   content: counter(count1) '.' counter(count2,lower-alpha) ' ';
}

Das Beispiel erzeugt die Zähler count1 und count2 auf dem <body>-Element. Damit sind sie im ganzen HTML Dokument sichtbar. Würde man sie auf den h1 oder h2 Elementen definieren, könnte die Verwendung von <section> oder <article>-Elementen die Zählung stören. Darauf gehen wir noch ein, wenn es um Vererbung von Zählern geht.

Der count1-Zähler wird in jeder h1-Überschrift um 1 erhöht. Der count2-Zähler wird je h1 wieder auf 0 gesetzt und in jeder h2-Überschrift erhöht, so dass die h1 Elemente über das ganze Dokument nummeriert werden und die Nummerierung der h2 Elemente mit jeder h1 Überschrift erneut beginnt.

Um die Nummerierung darzustellen, bekommen die h1- und h2-Elemente jeweils ein ::before-Pseudoelement hinzugefügt. Als Inhalt erhält dieses Pseudoelement in h1-Überschriften den Inhalt von count1. In h2-Überschriften wird der aktuelle Wert von count1, ein Punkt und dann der Wert von count2 ausgegeben. Der Wert von count2 wird aber nicht als Zahl ausgegeben, sondern als Kleinbuchstabe. An die Nummerierung wird dann noch eine Leerstelle angefügt, damit sie den richtigen Abstand vom Überschriftentext bekommt.

Auf diese Weise werden die Überschriften nun als "1", "1.a", "1.b", "2" und "2.b" durchnummeriert. Öffnen Sie das Beispiel gerne einmal im Frickl und probieren Sie aus, was geschieht, wenn Sie hinter dem Zählernamen in counter-increment einen anderen Wert als 1 setzen.

Hinweis:
Das Frickl-Beispiel verwendet h2 und h3 statt h1 und h2. Das ist dem Beispiele-Standardlayout geschuldet. Webseiten verwenden üblicherweise nur ein h1 Element. Mehrere h1 sind nicht verboten, kommen aber eher in längeren Dokumenten vor, die nicht speziell als Webseite gestaltet wurden.

HTML Listenzählung vs CSS Counter

HTML Listen werden vom Browser automatisch durchnummeriert. Der dafür verwendete Zähler wird, seit es CSS-Counter gibt, in Form des vordefinierten Counters list-item bereitgestellt. Sie können diesen Zähler genau wie selbst definierte Zähler ausgeben, inkrementieren und neu setzen.

list-item wird für alle HTML Elemente mit der Eigenschaft display:list-item automatisch um 1 erhöht. Das geschieht unabhängig davon, ob Sie einen eigenen Zähler mittels counter-increment verändern oder nicht. Nur dann, wenn Sie ausdrücklich list-item in einer der counter-...-Eigenschaften ansprechen, unterlässt der Browser die automatische Erhöhung.

Sie können list-item beispielsweise verwenden, wenn Sie die Listennummerierung explizit über das ::marker-Pseudoelement formatieren möchten. Ein Beispiel dafür finden Sie, wenn Sie dem Link folgen.

Geschachtelte Zähler

Zähler teilen sich mit Variablen die Eigenschaft, dass sie einen Gültigkeitsbereich haben. Und genau wie bei Variablen können Gültigkeitsbereiche auch geschachtelt werden. Auf Grund der Arbeitsweise von CSS Zählern – und auf Grund von Merkwürdigkeiten in der Spezifikation – ist dies nicht mit wenigen Worten erklärt

Erzeugen eines geschachtelten Gültigkeitsbereichs

Bitte betrachten Sie das nachfolgende Beispiel:

Obstsalat
ul {
   counter-reset: obst 0;
}
li {
   counter-increment: obst 1;
}
li::before, p::before {
   content: '(' counter(obst) ') ';
}
<ul id="fruit">
  <li>Bananen</li>
  <li>Äpfel
    <ul id="apples">
       <li>Cox Orange</li>
       <li>Boskop</li>
    </ul>
  </li>
  <li>Birnen
    <ul id="pears">
       <li>Forelle</li>
       <li>Williams Christ</li>
    </ul>
    <p>Glühbirnen</p>
    <ul id="pears2">
       <li>Conference</li>
       <li>Abate Fetel</li>
    </ul>
  </li>
</ul>

Die CSS-Regeln besagen, dass auf <ul>-Elementen ein Zähler namens obst erstellt und auf 0 gesetzt werden soll. Wir haben auch gelernt, dass ein Zähler für das Element, seine Kindelemente und seine nachfolgenden Geschwisterelemente sichtbar ist.

Im gezeigten Beispiel führt das zu mehreren Kollisionen. Zunächst wird auf dem <ul>-Element mit id="fruit" ein obst-Zähler definiert. Dieser gilt im gesamten Bereich des Beispiels. Das <li>-Element „Bananen“ inkrementiert ihn, das <li>-Element „Äpfel“ ebenso. Deswegen finden Sie vor „Bananen“ eine 1 und vor „Äpfel“ eine 2

Aber was ist nun mit dem <ul>-Element mit id="apples"? Auch hierfür gilt die CSS-Regel mit dem ul-Selektor, so dass erneut angefordert wird, einen Zähler namens obst zu erstellen. Dies geschieht auch, und dieser Zähler verdeckt den obst-Zähler vom fruit-Element. Es gibt nun zwei Zähler, die obst heißen, aber nur der, der zum apples-Element gehört, ist sichtbar. Die <li>-Elemente „Cox Orange“ und „Boskop“ erhöhen nur den sichtbaren Zähler. Deswegen finden sich vor diesem Apfelsorten wieder die Zählerwerte 1 und 2.

Nachdem die Liste mit Apfelsorten und das <li>-Element für Äpfel abgeschlossen sind, ist der Gültigkeitsbereich des neuen obst-Zählers zu Ende. Deswegen wird für das <li>-Element „Birnen“ wieder der obst-Zähler der fruit-Liste verwendet und vor den Birnen erscheint die Nummer 3. Für die Birnenliste gilt das Gleiche wie für die Äpfelliste, vor den Birnensorten stehen die Nummern 1 und 2.

Welchen Zählerwert haben nun die Glühbirnen? Die Birnenliste ist zu Ende, man könnte also meinen, dass wieder der obst-Zähler der fruit-Liste sichtbar ist. Dieser hätte den Wert 3, wir finden vor den Glühbirnen aber eine 2! Die Lösung lautet, dass dies der Zähler aus der pears-Liste ist, denn wie schon erwähnt, gilt ein Zähler für die Kindelemente und die nachfolgenden Geschwisterelemente desjenigen Elements, auf dem er definiert wurde.

Damit ist das Thema aber noch nicht fertig besprochen. Nach den Glühbirnen folgt eine weitere Birnenliste pears2. Auch diese Liste definiert einen neuen obst-Zähler, und vor Conference und Abate Fetel finden Sie dementsprechend die 1 und die 2. Aber wieviele Zähler haben wir an dieser Stelle nun? Vorhin schrieben wir, dass ein neuer, gleichnamiger Zähler einen vorhandenen Zähler überlagert. Demnach müsste es innerhalb der pears2-Liste also drei obst-Zähler geben. Andererseits wäre das unlogisch, denn die beiden Birnenlisten stehen ja nebeneinander.

Diese Frage klärt sich, wenn wir uns mit einer anderen Frage beschäftigen:

Wie gebe ich den Wert eines verdeckten Zählers aus – counters()

Wozu sollte das gut sein? Nun, für sich alleine ist ein verdeckter Zähler nicht unbedingt nützlich, aber wenn man eine geschachtelte Liste hat, möchte man vielleicht die Hierarchie der Nummerierungen ausgeben. Also vor den Cox Orange nicht einfach eine 1, sondern die 2.1, als erster Unterpunkt des zweiten Eintrags der Früchteliste. CSS bietet hierfür die Funktion counters() an.

Syntax

counters(zählername, zwischenzeichen, list-style-type)

Die counters()-Funktion benötigt im Vergleich zu counter() einen weiteren Parameter: das Zeichen (oder die Zeichenkette), die zwischen die Werte zweier Zählerinstanzen zu setzen ist. Der Stiltyp ist weiterhin optional und steht deswegen am Ende der Parameterliste. Wenn für den angegebenen Zählernamen nur ein Zähler erzeugt wurde, ist das Ergebnis von counters() identisch mit counter(). Gibt es aber mehrere, so werden alle Zähler dieses Namens, beginnend mit dem zuerst erzeugten, gemäß dem gewünschten Listenstil aufbereitet und zu einer langen Zeichenkette zusammengefügt. Zwischen den Zählerwerten wird jeweils das angegebene Zwischenzweichen eingefügt.

Verändern wir an unserem Obstsalatbeispiel eine Kleinigkeit und schauen uns an, was das bewirkt:

Hierarchisch nummerierter Obstsalat ansehen …
li::before, p::before {
   content: '(' counters(obst, '.') ') ';
}

Das Beispiel zeigt eine zweistufige Nummerierung bei den Äpfeln und beiden Birnenlisten.

Auch bei den Glühbirnen ist die counters()-Ausgabe zweistufig. Für sie gilt, wie beschrieben, noch der geschachtelte Zähler der ersten Birnenliste.

Und warum ist die zweite Birnenliste nicht dreistufig? CSS unterscheidet, ob ein Zähler von einem Eltern- oder Geschwisterelement geerbt wird. Das weiß es, weil ein Zähler immer dem Element zugeordnet ist, auf dem er erstellt wurde. Ein von Geschwistern geerbter Zähler wird ersetzt. Ein von Eltern geerbter Zähler wird hingegen überlagert.

Beachten Sie: Eine Mischung von Listenstilen ist bei einer counters()-Aufbereitung nicht möglich. Auf jeder Zählerstufe wird der gleiche Stil angewendet.

Überschriften mit geschachtelten Zählern

Zu Beginn des Artikels hatten wir eine Überschriftennummerierung vorgestellt, die mit unterschiedlichen Zählern je Überschriftenstufe arbeitet. Geht das auch mit geschachtelten Zählern?

Die Antwort lautet Im Prinzip schon, aber.... Damit counter-reset einen Zähler neu anlegt und einen gleichnamigen Zähler überlagert, muss dieser von einem Elternelement übernommen werden. Das bedeutet, dass Ihr HTML-Dokument exakt so aufgebaut sein muss, dass sich die inhaltliche Schachtelung als Elementschachtelung wiederfindet. Dazu können Sie das <section>-Element verwenden:

Dokumentstruktur mit Sections
<main>
  <section>
    <h1>Kapitel</h1>
    <p>Einleitung...</p>
    <section>
      <h2>Unterkapitel</h2>
      <p>Text Text...</p>
      <section>
        <h3>Unterunterkapitel</h3>
        ...
      </section>
      <section>
        <h3>Unterunterkapitel</h3>
        ...
      </section>
    </section>
    <section>
        <h2>Unterkapitel</h2>
      ...
    </section>
  </section>
  <section>
    <h1>Kapitel</h1>
    ...
  </section>
</main>

Ausgehend von dieser Struktur können Sie entweder auf section-Elementen oder den Überschriften h1 bis h6 einen Überschriftenzähler definieren.

Zählerdefinition für die Dokumentstruktur mit Sections
section:first-of-type { 
  counter-reset: abschnitt 0;
}
:is(h1,h2,h3,h4,h5,h6)::before {
  counter-increment: abschnitt;
  content: counters(abschnitt, '.');
}

Die erste Sub-Sektion einer Sektion erzeugt einen neuen, geschachtelten Zähler. Dieser gilt dann bis zum Ende der Sektion und wird bei jeder Überschrift hochgezählt.

Dieses Verfahren ist möglich, es ist aber nicht zu empfehlen, eine solche Struktur von Hand zu erstellen und intakt zu halten. Die Wahrscheinlichkeit, dass bei Umstrukturierungen des Texts die Struktur nicht sauber gepflegt wird, ist zu hoch. HTML ist keine Textverarbeitung.

+++ ab hier noch zu überarbeiten +++

Erzeugen einer verschachtelten Zählhierarchie ansehen …
ol {
    counter-reset: table-of-content;
    list-style-type: none;
}
li::before {
    counter-increment: table-of-content;
    content: counters(table-of-content,".", decimal) " ";
	color: red;
	font-weight: bold;
}

Das CSS zählt verschachtelte Listenelemente als "1", "1.1", "1.1.1", usw.

Die counters()-Funktion benötigt einige Zeilen weniger, kann aber nicht für die Zählung verschiedener Elemente, bzw. für unterschiedliche Formatierungen verwendet werden.

Beachten Sie: counters() funktioniert nur dann richtig, wenn Ihr Listen-Markup gültig ist. Eine geschachtelte Liste ist immer auch ein Listenelement, muss also in <li>...</li> eingeschlossen sein. Wenn Sie das vergessen, werden die li-Elemente hinter der geschachtelten Liste falsch nummeriert. An diesem Problem wird zwar auch seitens der Spezifikationsautoren und Browserhersteller gearbeitet, aber das hat zu Unfug in der Lists and Counters-Spezifikation geführt und nur Firefox hat bisher versucht, daraus eine sinnvolle Implementierung zu machen.

dynamisch erstelltes Inhaltsverzeichnis

Häufig wird so eine verschachtelte Kapitelzählung wie im vorletzten Abschnitt auch in einem Inhaltsverzeichnis aufgenommen, um am Seitenanfang interne Links auf die jeweiligen Kapitel zu richten.

In Content Management Systemen wie unserem Wiki werden diese Inhaltsverzeichnissse dynamisch erstellt.[1] Diese Komfort-Funktion wollen wir mit JavaScript nachbauen, indem wir alle h2- und h3-Überschriften auslesen und eine entsprechende Navigation erstellen.[2][3]


Einhängen des Inhaltsverzeichnisses

Seiten mit mehreren Überschriften sollen nun ein Inhaltsverzeichnis erhalten. Dies soll aber nicht vom Anwender bereits im HTML-Markup vorgesehen, sondern dynamisch eingefügt werden:

Einhängen des ToC ansehen …
function generateToC() {
	document.querySelector('h1').insertAdjacentHTML('afterend', `
		<nav aria-labelledby="sections-heading">
			<h6 id="sections-heading">Inhaltsverzeichnis</h6>
			<ol>
			</ol>
		</nav>
	`);
}

Unser Inhaltsverzeichnis besteht aus einer (noch) leeren ol-Liste, die von einem nav-Element umschlossen wird. Über ein aria-labelledby-Attribut wird der Zusammenhang zur h6-Überschrift hergestellt. Das Ganze wird mit insertAdjacentHTML nach der (hoffentlich) nur einmal im Dokument vorkommenden h1-Überschrift eingehängt.

Erzeugen der Links und der Seitenanker

Mit querySelectorAll('h2, h3, h4') werden alle Überschriften der zweiten, dritten und vierten Kategorie selektiert und in einer live node list gespeichert. Dann werden die benötigten Informationen extrahiert:

  • Der Text innerhalb der Tags
  • Die Hierarchietiefe (H2 oder h3)
  • die Element-id, auf die verlinkt werden soll. Falls keine id existiert, muss eine angelegt werden!
Auslesen der Überschriften ansehen …
function generateToC() {
  ...
// alle Überschriften sammeln
  document.querySelectorAll('h2, h3, h4, h5').forEach(heading => {
		const
			ul = document.querySelector('[aria-labelledby="sections-heading"] ol'),
			li = ul.appendChild(document.createElement('li')),
			a = li.appendChild(document.createElement('a'));

		// erzeuge eine ID falls keine vorhanden
		if (!heading.hasAttribute('id')) {
			// verwende Textinhalt der Überschrift in Kleinbuchstaben
			heading.id = heading.textContent.toLowerCase();
		}

		a.href = '#' + heading.id;
		a.appendChild(document.createTextNode(heading.textContent));

		// Ebene für Einrückungen
		if (heading.tagName != 'H2') {
			li.classList.add(
				'toc-level-' + (
					parseInt(heading.tagName.replace(/h/i, ''))
					-1
				).toString()
			);
		}
	});

Die gefundenen Ergebnisse sind nun in einer live node list, die mit einer forEach-Schleife jetzt für jeden Treffer

  • mit textContent die Überschrift ausliest und,
  • wenn die id noch keinen Wert hat, dieser den Text in Kleinbuchstaben zuweist.
  • Die Werte in einen Listeneintrag mit insertAdjacentHTML einfügt.

Dann wird ein Link erzeugt:

  • href besteht aus der Raute für den Seitenanker und heading.id
  • Der Linktext wird mit createTextNode aus heading.textContent erzeugt und dann mit appendChild eingehängt.

Zum Schluss werden die tagNames überprüft, und für h3-h5 Klassen zugewiesen, die per CSS Einrückungen erzeugen.

Wie Counter funktionieren

Zum besseren Verständnis von Countern soll zum Abschluss noch auf die genaue Realisierung dieses Konzepts eingegangen werden.

Die Zählerliste und Wertevererbung

Jedes Element im DOM besitzt eine Zählerliste (counter set). Sie wird zunächst durch Vererbung gefüllt, und zwar

  • aus den Zählern in der Zählerliste seines Elternelements
  • aus den Zählern in der Zählerliste seines vorhergehenen Geschwisterelements.

Existiert auf Elternelement und vorhergehendem Geschwisterelement ein Zähler mit gleichem Namen, so werden gemäß dem Arbeitsentwurf der Spezifikation vom 09.07.2020 beide Zähler übernommen. Der Zähler aus dem Geschwisterelement überlagert dabei den Zähler des Elternelements. Der nachfolgende Arbeitsentwurf vom 17.11.2020 besagt hingegen, dass der Zähler des Geschwisterelements nur übernommen werden soll, wenn es keinen gleichnamigen Zähler auf dem Elterelement gibt. Diese Änderung wird bisher nur von Firefox realisiert, und auch nur für Listen! Siehe dazu auch den unten stehenden „Beachten“ Einschub und das nachfolgende Kapitel)

CSS hält für jeden Zähler das Element fest, in dem er definiert wurde, so dass auch nach mehrfacher Vererbung eines Zählers immer noch bekannt ist, wo er ursprünglich herkam.

Das gilt aber nur für die Zähler selbst, nicht ihre Werte. Die Werte der so gefundenen Zähler werden aus dem Element übernommen, das dem betrachteten Element in der Baumreihenfolge des DOM vorangeht. Auf diese Weise ist es möglich, auch über tiefer geschachtelte HTML-Strukturen hinweg fortlaufende Zähler zu erzeugen.

ToDo (weitere ToDos)

Bild mit Visualisierung der Vererbung
Beachten Sie: Die Vererbungsregel vom Juli 2020, dass Zähler auf dem vorhergehenden Geschwisterelement Vorrang vor einem gleichnamigen Zähler des Elternelements haben, führt zu Problemen bei falsch geschachtelten Listen. Normalerweise muss eine geschachtelte Liste mit <li>...</li> umgeben werden, aber viele Autoren und auch HTML-Tools tun das nicht. Erstellt man dann mit counters() eine hierarchische Nummerierung, ist sie hinter der geschachtelten Liste falsch. Der Arbeitsentwurf von November 2020 möchte das lösen und, indem Zähler vom Geschwisterelement keine Zählerschachtelung auslösen, wenn sie damit einen Zähler aus dem Elternelement überlagern würden. Das stellt allerdings einen breaking-change für die Semantik von Zählern dar und wurde deshalb in Chrome bisher (Januar 2024) nicht implementiert. Firefox implementiert es, aber nur für Listen.

Erzeugen von Zählern

Nachdem alle vererbten Zähler in die Zählerliste eines Elements eingetragen und mit Werten versehen wurden, werden die CSS-Eigenschaften des Elements selbst verarbeitet. Diese können neue Zähler anlegen und die Werte bestehender Zähler verändern.

Die Eigenschaften counter-increment und counter-set erzeugen nur dann einen neuen Zähler, wenn noch kein Zähler mit dem verwendeten Namen existiert. Andernfalls modifizieren sie den vorhandenen Zähler - bei einem Stapel gleichnamiger Zähler den, der „oben“ auf dem Stapel liegt.

Das Abrufen eines bisher undefinerten Zählers mit counter() oder counters() erzeugt ebenfalls einen neuen Zähler mit diesem Namen.

Die counter-reset-Eigenschaft erzeugt auf jeden Fall einen neuen Zähler und weist ihm einen Wert zu. Falls ein gleichnamiger Zähler bereits existiert und vom Elternelement geerbt wurde, wird ein neuer Zähler mit gleichem Namen angelegt, der den geerbten Zähler überlagert. Auf diese Weise kann ein Stapel aus Zählern gleichen Namens entstehen. Ein Zähler, der von einem Geschwisterelement geerbt wurde, wird hingegen ersetzt.

Auf diese Weise werden Zähler für geschachtelte Listen realisiert, counter-increment, counter-set und counter() greifen immer auf die Zählerinstanz zu, die zum nächstgelegenen Elternelement gehört. Die counters() Funktion sammelt hingegen die Werte aller Zählerinstanzen dieses Namens ein, womit sich hierarchische Nummerierungen erzeugen lassen.

Manipulieren von Zählern

Außer einer einfachen Inkrementierung unterstützt counter-increment auch eine explizite Angabe des Wertes, der auf den Zählerstand aufaddiert werden soll. Wenn Sie einen reversed()-Counter verwenden, müssen Sie explizit den Wert -1 verwenden. reversed-Counter sind zwar zum Abwärtszählen gedacht, aber der Defaultwert von counter-increment stört sich daran nicht.

Zählen in Zweierschritten
p {
   counter-increment: absatz 2;
}

Die Eigenschaft counter-reset legt den rückgesetzten Zähler grundsätzlich neu an. Wenn man lediglich den Wert eines geerbten Zählers auf einen neuen Wert setzen will, ist counter-reset deshalb nicht brauchbar. Hierfür gibt es die counter-set Eigenschaft, mit der ein geerbter Zähler auf einen neuen Wert gesetzt werden kann.

Reversed Zähler

Ein reversed() Zähler kann mit counter-reset erzeugt werden und verhält sich im Prinzip wie ein normaler Zähler. Selbst der Standardwert für counter-increment ist immer noch +1. Die Besonderheit eines solchen Zählers ist, dass man ihm keinen Anfangswert zuweisen muss. Man kann es natürlich, wenn man möchte, aber dann hat reversed() keine zusätzliche Funktion.

Wenn der Browser einen reversed()-Zähler ohne Initialwert erzeugt, analysiert er während der Erstellung des Seitenlayout den Geltungsbereich dieses Zählers, und zwar in Baumreihenfolge des DOM. Dieser Geltungsbereich besteht aus den Kindelementen des Elements, auf dem der Zähler erzeugt wird, sowie aus seinen nachfolgenden Geschwisterelementen und deren Kindern (also all die Elemente, die diesen Zähler als Wertequelle nutzen können). Der Geltungsbereich wird dort unterbrochen, wo mittels counter-reset ein anderer Zähler dieses Namens erzeugt wird.

Der Browser beginnt nun mit einem Startwert von 0. Findet er in im Geltungsbereich counter-increment Angaben für diesen Zähler, zieht er ihren Inkrementwert vom Startwert ab. Der erste Inkrementwert wird dabei doppelt gerechnet, das ist erforderlich, damit das Ergebnis am Ende passt. Falls er im Geltungsbereich eine counter-set-Angabe findet, addiert er den set-Wert zum Startwert und bricht den Durchlauf ab.

Der reversed() Zähler wird dann auf den so gefundenen Startwert initialisiert. Auf diese Weise wird erreicht, dass ein reversed()-Zähler, in dessen Geltungsbereich ein counter-set steht, exakt an diesem Wert ankommt. Ohne counter-set entsteht der Effekt, dass der Zähler bei 1 endet. Probieren Sie es aus!

Achtung!

Bei großen Dokumenten kann diese Analyse die Layoutphase des Browsers verzögern. Nutzen Sie reversed()-Zähler vorsichtig beziehungsweise messen Sie die Performance ihrer Seite.

Siehe auch

  • Bildergalerie mit Grid Layout, deren Kindelemente sich an den verfügbaren Platz anpassen. Zur besseren Kennzeichnung der Reihenfolge im Markup wurden sie mit counter() nummeriert.

Weblinks

  • Hilfe:Wiki/Inhaltsverzeichnis
  • css-tricks: Parsing Markdown into an Automated Table of Contents von Lisi Linhart am 13.11.2020
  • A Perfect Table of Contents With HTML + CSS von Nicholas C. Zakas on May 25, 2022 (css-tricks.com)