Navigation/Flyout-Menü
Gerade auf kleinen Bildschirmen und für Screenreader ist es oft wünschenswert, gleich zum Inhalt zu kommen, ohne sich lange mit der Navigation aufzuhalten. Hier gibt es zwei Möglichkeiten:
- ein Skip-Link ermöglicht es, die Navigation zu überspringen
- ein Toggle-Menü versteckt die Navigation und klappt sie nur bei Bedarf aus. Wir zeigen Ihnen zwei Ansätze. Zuerst mit Button und etwas JavaScript, dann eine Variante mit details ohne JavaScript.
Inhaltsverzeichnis
Skiplink
Auf einem normalen Monitor ist die Dropdown-Navigation im Ausgangszustand eingeklappt und lässt sich mit einem Blick nach unten übergehen, während auf Screenreader angewiesene Benutzer sich durch alle Links durchtabben müssten. Mit einem Skipklink, der ganz am Anfang im Markup steht und auf den Hauptinhalt gerichtet ist, können Sie das Menü überspringen. Im Normalzustand ist der Skip-Link per CSS außerhalb des sichtbaren Bereichs positioniert.[1]
<a href="#main-content">zum Inhalt</a>
<nav>
<ul>
<li><a aria-current="page">Home</a></li>
<li><a href="#">Seite 2</a></li>
<li><a href="#">Seite 3</a></li>
<li><a href="#">Seite 4</a></li>
<li><a href="#">Kontakt</a></li>
</nav>
<main id="main-content">
Skiplinks werden am logischen Beginn des Dokuments notiert und enthalten zum Beispiel:
- zum Inhalt
- zur Navigation
- zur Sitesearch
Mit Software wie VoiceOver und anderen Screenreadern wird solch ein Link einfach als „Link zum Inhalt“ vorgelesen.
Flyout-Menü mit toggle-Button
Um Platz für Inhalte zu schaffen, soll die Navigation nur bei Bedarf eingeblendet werden. Deshalb erweitern wir unsere Flyout-Navigation aus dem letzten Kapitel um einen toggle-Button. Im Grundzustand ist nur ein Navicon sichtbar - erst ein Klick auf dieses öffnet das Menü.[2]
Die vorliegende Navigation basiert auf einem Entwurf von Ahmad Shadeed für a11ymatters.com.[3]
HTML-Markup
Es mag trivial scheinen, aber eine sorgfältige Auswahl der verwendeten HTML-Elemente erleichtert die volle Zugänglichkeit, damit das Menü von allen Benutzern mit Maus, Tastatur und Screenreadern „gelesen“ und bedient werden kann.
<nav>
<button>Menü</button>
<ul>
<li><a aria-current="page">Home</a></li>
<li><a href="#">Seite 2</a></li>
<li><a href="#">Seite 3</a></li>
<li><a href="#">Seite 4</a></li>
<li><a href="#">Kontakt</a></li>
</nav>
Wir verwenden, wie im Grundstruktur-Kapitel besprochen:
- ein nav-Element als Container.
Dies hat gegenüber einem inhaltsleeren div den Vorteil, dass Screenreader dem Nutzer die Bedeutung des Elements vorlesen. - einen button[4]
Dieser hat gegenüber einem inhaltsleeren span bereits ein Standardverhalten implementiert. Man kann ihn mit Maus oder Tastatur anwählen. Dann erhält er den focus.
Durch die Positionierung innerhalb des nav-Elements wird er diesem direkt zugordnet. - eine ul, die die Listenelemente mit den darin befindlichen Links enthält.
nav
-Element im Ganzen, sondern nur die ul
mit den Links ausgeblendet werden. So können Nutzer von Screenreadern sofort erkennen, dass es eine Navigation gibt und dass der Button zu ihr gehört und diese steuert.Steuerung mit JavaScript
Nun soll die Navigation mit CSS versteckt und mit JavaScript wieder eingeblendet werden. Dabei soll die Navigation immer bedienbar sein, auch wenn CSS oder JS nicht geladen oder ausgeführt werden können:[5]
Dies ist progressive enhancement , eine schrittweise Verbesserung
- Nur HTML: In diesem Fall wird der Benutzer sowohl den Button als auch die Navigationsliste sehen. Jetzt ist unsere JavaScript-gesteuerte Schaltfläche nutzlos und tut nichts.
- HTML + CSS: Das Gleiche wie vorher, aber mit einem besseren Aussehen und Gefühl. Beachten Sie, dass unser Button nicht vorhanden ist, warum? Wir werden uns das in Kürze ansehen.
- HTML, CSS + JavaScript: Jetzt haben wir unseren Button und das Navigationsmenü ist ausgeblendet. Wir können auf den Button klicken und die Anzeige des Menüs ein- und ausschalten.
Um die obige Funktionalität zu erreichen, müssen wir Folgendes tun:
- Blenden Sie den Button mit CSS aus.
- Prüfen Sie, ob JavaScript verfügbar ist.
- Kein JavaScript: Das Navigationsmenü bleibt erhalten.
- JavaScript: Ausblenden des Navigationsmenüs, Einblenden der Schaltfläche mit CSS.
CSS
Schritt 1 ist unkompliziert. Neben einigen grundlegenden Formatierungen setzen wir den Button auf display: none
.
:root {
--blue: #337599;
--blue4: #adc8d6;
--black: #113;
--yellow: #dfac20;
}
body {
background: var(--black);
color: white;
}
a {
color: var(--blue4);
}
nav li {
list-style: none;
margin-bottom: 0.25em;
}
a:hover,
a:focus {
color: var(--yellow);
}
Script
Nun wird geprüft ob JavaScript verfügbar ist.
Falls nicht, bleibt der Button ausgeblendet und die Navigation immer sichtbar und funktionsfähig.
Falls dies zutrifft, erhält das html-Element eine Klasse js
.
const root = document.documentElement;
root.classList.add('js');
Über diese Klasse können nun die Elemente unserer Navigation selektiert werden, um jetzt die Navigation aus und den Button einzublenden. Die Formatierung selbst steuert CSS:
.js nav ul { display: none; /* hide the navigation list when JS is available */ } .js nav button { display: block; /* show the button JS is available */ }
Diese Vorgehensweise hat zwei Schwächen:
- die Anzahl der Selektoren wird immer länger
- es ist Screenreadern alleine aus dem HTML und CSS nicht ersichtlich, ob die Elemente versteckt oder sichtabr sind.
Dies wird im nächsten Script kann so erweitert, dass die Zustände berücksichtigt werden.
Im allgemeinen Gebrauch haben sich als Symbol oder Icon für einen Navigations-Button drei waagerechte Striche durchgesetzt. Deshalb wird ein solches Menü auch oft „Burgermenü“ oder „Hamburgermenü“ genannt. Sie können bei Verwendung der Zeichencodierung utf-8 entweder direkt „☰“ oder ☰
eingeben.
<button> Menu <span class="close-icon">×</span> <span class="burger-icon">☰</span> </button>
Bei diesem Ansatz fügen wir dem Button sowohl ein x
als Schließen-Symbol und ein „Hamburger-Symbol“ hinzu. Sobald der Benutzer den Button betätigt, wird das Hamburger-Symbol ausgeblendet und durch das Schließen-Symbol ersetzt.
Diese Methode hat mehrere Nachteile:
- Bildschirmlesegeräte werden diese Symbole mit ihrem Namen vorlesen, was sehr verwirrend ist.
- ×: menu times, toggle button navigation 1 item
- ☰: menu trigram for heaven, toggle button navigation 1 item
Zumindest sollten sie vor Screenreadern mit dem Attribut aria-hidden verborgen werden.
- Durch die unterschiedliche Größe der Zeichen ist eine Formatierung mit CSS umständlich
Einfacher und zugänglicher ist es, den Text des Buttons visuell zu verstecken. Dies kann mit einem Pseudoelement oder einem SVG als Hintergrundgrafik realisiert werden.
Zustand mit ARIA-Attributen anzeigen
Ist der button nun geklickt oder nicht? Das kann man nicht gleich erkennen. ARIA-Attribute können interaktive Elemente zugänglicher machen, indem sie Zustände anzeigen:
<nav>
<button id="toggle" aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu">
...
Zuerst wird unser HTML-Markup geändert. Der Button erhält neben seiner id nun zwei Attribute:
- aria-expanded zeigt an, ob der Button gerade aus- oder eingeklappt ist.
- aria-controls identifizert ein Element, dessen Inhalt durch das aktuelle Element kontrolliert wird.
Die Liste innerhalb des nav-Elements erhält die id menu
und wird so mit dem button verknüpft!
Die jeweiligen Werte werden durch das Script geändert.
const toggle = document.querySelector('#toggle'),
menu = document.querySelector('nav ul');
toggle.addEventListener('click', function(){
if (menu.classList.contains('is-active')) {
this.setAttribute('aria-expanded', 'false');
menu.classList.remove('is-active');
} else {
menu.classList.add('is-active');
this.setAttribute('aria-expanded', 'true');
}
});
Wenn Sie das Beispiel mit Klick auf [Vorschau] in einem neuen Tab öffnen; können Sie das HTML im Seiteninspektor inspizieren.
Mit jedem Klick werden die aria-expanded-Zustände neu gesetzt.
Das fertige Beispiel
Ein Screenreader liest den Button mit seinem Text 'Menü' vor - visuell können wir den Text verstecken und durch ein Navicon, bzw. ein Schließen-'X' ersetzen:
[aria-expanded] {
width:2em;
height: 2em;
background: transparent;
color: transparent;
outline:transparent;
border: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M1,2 h7 M1,5 h7 M1,8 h7' fill='none' stroke='%23a8c76b' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
}
[aria-expanded="true"] {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M2,2 l6,6 M8,2 l-6,6' fill='none' stroke='%23c82f04' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
}
Der Button erhält transparente Rahmen und Hintergründe. Über den Attributspräsenz-Selektor [aria-expanded]
wird nun unser Navicon als SVG-Hintergrundbild eingeblendet.
Ändert sich der Wert durch Anklicken, wird nun das Schließen-Symbol angezeigt.
Alternative: details
Die Toggle-Funktionalität des Flyout-Menüs wurde bisher über den Button und das dazugehörige JavaScript abgewickelt.
Seit mehreren Jahren gibt es so etwas auch als natives HTML-Element. Mit details und summary können Sie Inhalte auf- und wieder zuklappen. Dieses Standardverhalten macht sich folgendes Beispiel zunutze, das so auf JavaScript verzichten kann:
<nav role="navigation">
<details>
<summary><span>Menü</span></summary>
<ul id="menu">
<li><a aria-current="page">Home</a></li>
<li><a href="#">Seite 2</a></li>
<li><a href="#">Seite 3</a></li>
<li><a href="#">Seite 4</a></li>
<li><a href="#">Kontakt</a></li>
</ul>
</details>
</nav>
Dieses Beispiel ist auch mit Tastatur und Screenreader benutzbar. Einige 2019 noch vorhandene Bugs bei NVDA und Firefox (<71) wurden mittlerweile behoben.[6]
Bei :hover wird das summary-Element allerdings nicht gekennzeichnet. Dies wurde hier durch CSS ergänzt:
nav summary {
cursor:pointer;
}
nav summary:hover {
font-size:2.2em;
text-shadow: 2px 2px 5px white;
}
Achtung!
Trotzdem würde ich persönlich die obere Variante mit JavaScript empfehlen.
--Matthias Scharwies (Diskussion) 09:27, 19. Feb. 2023 (CET)Fazit
Ein solches Menü eignet sich gleichermaßen für OnePager wie für kleinere Webauftritte. Allerdings gibt es Probleme mit dem Vorlesen durch Screenreader, sodass die obere Variante mit JavaScript zu bevorzugen ist.
Für größere DropDown-Menüs stellt sich die Problematik des Auf- und Zuklappens bei jeder neuen Unterliste. Hier empfiehlt sich der Einsatz einer JavaScript-Lösung, wie sie im vorigen Kapitel vorgestellt wurde.
Das 2019 geschriebene Tutorial einer zugänglichen Dropdown-Navigation mit summary und details wurde aus diesen Gründen depubliziert.
Quellen
- ↑ SELF-Blog: Skipper ahoj! von Gunnar Bittersmann am 15.07.2018
- ↑ W3C: Fly-out Menus Tutorial der WAI
- ↑ a11ymatters.com: Accessible Mobile Navigation von Ahmad Shadeed
- ↑ Ahmad Shadeed überlegte auch einen Link zu verwenden, dessen href-Attribut auf die id des ul-Elements zeigte. Insoweit ok, aber zum Schließen des Menüs benötigt man eben einen Button und keinen Link!
- ↑ Ahmad Shadeed zeigte in seinem Artikel in Kapitel 3- Don’t hide the <nav> element, wie man die Navigation nun per CSS aus- und mit JavaScript wiedereinblendet. Dies scheint logisch, führt aber zu Problemen, wenn aus Gründen kein JavaScript geladen oder ausgeführt werden kann. Dann gibt es gar keine Navigation.
- ↑ Accessible accordions part 2 – using <details> and <summary> von Graham Arnfield