Beispiel: Seitennavigation mit popover

Was?

Die Navigation soll folgende Eigenschaften haben:

Wie?

Basis der Navigation ist eine verschachtelte Liste. Das Öffnen des Menüs bzw. der Untermenüs erfolgt über einen Button direkt vor den UL mit der popover-Technik. Die Positionierung der Untermenüs erfolgt über die anchor-Technik.

Vor die Navigation wird noch ein Skip-Link gesetzt, um Tastatur-Benutzern sowie Besuchern mit assistiven Techniken zu ermöglichen, direkt zum Inhalt zu springen. Per css wird dieser Link aus dem Viewport geschoben und nur bei Focus sichtbar.

Um Besucher mit assistiven Techniken zu informieren, erhält die Navigation noch eine visuell versteckte Überschrift.

Per css wird die Navigationsliste je nach Seitenbreite im Quer- oder Hochformat angeordnet.

Auf schmalen Viewports wird die Navigation hinter einem Menü-Button versteckt. Bei Klick öffnet sich die erste Ebene nach unten und die zweite nach rechts. Auf genügend breiten Viewports ist der Menü-Button ausgeblendet und die erste Ebene ist immer sichtbar und waagrecht angeordnet. Die zweite Ebene öffnet nach unten.

In die Navigation wurde auch ein Untermenü für die Sprachwahl eingebaut. Damit das Sprachwahlmenü unabhängig von der Sprache erkannt wird, wurde hier das durch die „Language Icon Initiative” vorgeschlagene Standard-Icon für Sprachwahlmenüs gewählt.

In der Beispieldatei sind HTML, CSS und Javascript in einer Datei zusammengefasst. Im Einsatz sollten die Teile in getrennten Dateien untergebracht werden.

HTML

Das HTML für ein (Unter-)Menü besteht aus einer Liste mit den Links und einem Button, der diese Liste "öffnet". Für die popover-Technik muss die Liste eine id und das Attribut popover haben. Der Button benötigt die Attribute popovertarget und popovertargetaction.

<popovertarget="level11" popovertargetaction="toggle">Bereich 1</button>
<ul id="level11" popover>						
	<li><a href=''>Seite 1.1</a></li>
	<li><a href=''>Seite 1.2</a></li>
	<li><a href=''>Seite 1.3</a></li>
</ul>

Der link zur aktuellen Seite hat kein href-Attribut, statt dessen aber das Attribut tabindex=0. Die Listenelemente, in denen sich dieser Link befindet, erhalten das Attribut aria-current='page'.

<li aria-current='page'><a tabindex=0>aktuelle Seite</a></li>

CSS

Die Positionierung der (Unter-)Menüs erfolgt relativ zu den button, die sie öffnen. Dazu muss eine Verbindung zwischen der Liste und dem Button hergestellt werden. Dieses erfolgt über die css-Regel position-anchor: auto;. Die Positionierung erfolgt dann über:

position-anchor: auto;
position: absolute;
top: anchor(bottom);
left: anchor(left);

bzw.

top: anchor(top);
left: calc(anchor(right) + .4em);

Bei den button, die die Untermenüs öffnen, soll angezeigt werden, ob das Untermenü geöffnet ist. Dieses erfolgt über folgenes CSS, bei dem mit der Pseudoklasse has und den Nachbarselektor + ermitelt wird, welcher button ein geöffnetes Popover als Nachbarn hat:

& button::after {
	content: '☰' / '';
}
& button:has(+:popover-open)::after {
	content: '×' / '';
}

Der Link zur aktuellen Seite witd über die im HTML gesetzten Attribute mit folgendem CSS gekennzeichnet :

& li[aria-current] a[tabindex]::before { 
	content: '►' / 'Aktuelle Seite';
	text-align: start;
	width: 1.5em;
}
& [popover] button:has(+ [popover] > li[aria-current]) {
	border-left: 2px solid black; 
	padding-left: .2em;
	margin-left: 0;
}

Das Javascript

Über die ESC-Taste oder durch Mausklick außerhalb des Menüs wird das Menü bzw. ein offenes Untermenü geschlossen. Beim Verlassen des Menüs mit der Tabulatortaste bleibt das Menü aber offen. Zum automatischen Schließen wird ein einfaches Javascript benötigt, das im focusout-Event prüft, ob das Element, das dann den Focus erhält (relatedTarget), außerhalb des Menüs liegt, und dann die offenen (Unter-)Menüs schließt. Dazu kommen die Methoden contains und hidePopover zum Einsatz:

<script type="module">
	/* Schließen des offenen Menüs beim Verlassen mit Tabulator */
	const sitenav = document.querySelector("#sitenav");
	sitenav.addEventListener("focusout", focusoutEvent => {
		if(!sitenav.contains(focusoutEvent.relatedTarget))
			sitenav.querySelectorAll(':popover-open').forEach(ele => ele.hidePopover());
	});
</script>

Probleme

Stand Oktober 2025 unterstützten noch nicht alle Browser die Anchor-Technik, siehe. Caniuse. Für die anderen Browser werden mit Hilfe von @supports not (position-anchor: auto) die Untermenüs frei positioniert.