Hamburger Menu HTML

Drei Striche brauchen einen Namen

Menübutton, Menülinks, Zustand: drei Stellen im mobilen Menü.

Website prüfen
Beispiel im Prüfbericht Markierter Befund
Markierter Befund · Kritisch · WCAG 4.1.2Tauschen-Button ohne Namen

Zustandsplan statt Icon-Trick

Ein Menü, vier Ansichten

Der Breakpoint ändert das Layout. Der Button ändert den Zustand. Beides muss dieselbe Navigation steuern, ohne Links zu duplizieren.

Viewport × Zustand

Die vollständige Zustandsmatrix

Bei 48rem wechselt nur die Darstellung. Auf Mobilgeräten entscheidet aria-expanded.

01
Mobil · geschlossenStartzustand
NMenü
Button
sichtbar
aria-expanded
false
nav
hidden
02
Mobil · geöffnetNach Enter oder Klick
NMenü
LeistungenReferenzenKontakt
Button
sichtbar
aria-expanded
true
nav
sichtbar
03
Desktop · vorher geschlossenBreakpoint überschritten
NAngebotArbeitKontakt
Button
ausgeblendet
mobiler Zustand
zurückgesetzt
nav
sichtbar
04
Desktop · vorher geöffnetGleiches Ergebnis
NAngebotArbeitKontakt
Button
ausgeblendet
mobiler Zustand
zurückgesetzt
nav
sichtbar
Die beiden Desktop-Fälle enden absichtlich gleich. Sonst könnte ein auf Mobilgeräten geschlossenes Menü nach dem Verbreitern leer bleiben.

A · Beziehung

Drei Werte, eine Entscheidung

Der Schalter trägt den Namen und den Zustand. aria-controls verweist auf die ID der Navigation. hidden bestimmt, ob deren Links gerendert und fokussierbar sind.

B · Tastaturroute

Öffnen, durchlaufen, sicher zurückkehren

Normale Links bleiben normale Tab-Ziele. Zusätzliche Pfeiltasten und role="menu" sind für eine Seitennavigation nicht nötig.

  1. TabMenübuttonsichtbarer Fokus
  2. EnterNavigation offenoder Leertaste
  3. TabErster Linkdanach Link für Link
  4. EscMenübuttonschließen + Fokus zurück

C · Referenzimplementierung

Eine Navigation, vollständig verdrahtet

Die Funktion setState schreibt Sichtbarkeit und Ansage gemeinsam. Beim Wechsel auf Desktop wird das Menü sichtbar; beim Rückweg auf Mobil startet es geschlossen.

HTMLSemantik
<button class="nav__toggle" type="button"
  aria-expanded="false"
  aria-controls="hauptmenue">
  <span class="nav__icon" aria-hidden="true"></span>
  <span>Menü</span>
</button>

<nav id="hauptmenue"
  aria-label="Hauptnavigation" hidden>
  <ul class="nav__list">
    <li><a href="/leistungen">Leistungen</a></li>
    <li><a href="/referenzen">Referenzen</a></li>
    <li><a href="/kontakt">Kontakt</a></li>
  </ul>
</nav>
JavaScriptZustand + Breakpoint
const toggle = document.querySelector('.nav__toggle');
const nav = document.querySelector('#hauptmenue');
const desktop = matchMedia('(min-width: 48rem)');

function setState(open) {
  if (desktop.matches) {
    nav.hidden = false;
    toggle.setAttribute('aria-expanded', 'false');
    return;
  }

  nav.hidden = !open;
  toggle.setAttribute('aria-expanded', String(open));
}

toggle.addEventListener('click', () => {
  const open = toggle.getAttribute('aria-expanded') !== 'true';
  setState(open);
});

document.addEventListener('keydown', (event) => {
  if (event.key !== 'Escape' || nav.hidden || desktop.matches) return;
  setState(false);
  toggle.focus();
});

desktop.addEventListener('change', () => setState(false));
setState(false);
CSSMobile zuerst
.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  min-height: 44px;
}

.nav__list {
  display: grid;
  gap: .75rem;
  margin: 1rem 0 0;
}

@media (min-width: 48rem) {
  .nav__toggle { display: none; }
  .nav__list {
    display: flex;
    gap: 1.5rem;
    margin: 0;
  }
}

D · Prüfprotokoll

Der Resize-Test gehört dazu

  1. 320 px

    Mit Tab zum Button, mit Enter öffnen, alle Links durchlaufen.

  2. Escape

    Aus einem Link heraus schließen; Fokus muss wieder auf „Menü“ stehen.

  3. ≥ 48 rem

    Fenster verbreitern: Button verschwindet, Navigation bleibt vollständig sichtbar.

  4. Zurück

    Wieder schmal ziehen: Button erscheint mit false, Navigation ist geschlossen.

Aus dem Prüfbericht

Drei Regeln, drei Befunde

Kritisch Die drei Striche haben keinen Namen Regel button-name

Das Symbol ist mit aria-hidden ausgeblendet, weiterer Text fehlt. aria-label="Menü" gibt der Schaltfläche im Kopfbereich ihren Namen.

Anleitung: Schaltflächen zugänglich beschriften

Kritisch Der Zustand des Menüs ist ungültig Regel aria-valid-attr-value

aria-expanded="maybe" beschreibt keinen Zustand. Geschlossen ist false, offen ist true; das Skript setzt beides.

Anleitung: Gültige ARIA-Attributwerte setzen

Zum Mitnehmen

Das mobile Menü, korrigiert

Zwei Änderungen im HTML, eine im Umschalter.

Korrektur in 3 Schritten ansehen
  1. Menübutton benennen und Zustand setzen

    aria-label gibt der Schaltfläche ihren Namen. aria-expanded beginnt mit false, weil das Menü geschlossen startet.

    KorrekturvergleichSchritt 1 · HTML

    Vorher

    <button id="menue-schalter" type="button"
      aria-controls="hauptmenue" aria-expanded="maybe">
      <span aria-hidden="true">☰</span>
    </button>

    Nachher

    <button id="menue-schalter" type="button" aria-label="Menü"
      aria-controls="hauptmenue" aria-expanded="false">
      <span aria-hidden="true">☰</span>
    </button>

    Markierte Zeilen wurden geändert

    So prüfen Sie es Gehen Sie mit der Tabulatortaste auf die drei Striche. Ein Vorleseprogramm sagt „Menü, Schaltfläche, reduziert“.

  2. Den Pfeil-Link beschriften

    Der Linktext nennt sein Ziel. Ein Pfeil allein bleibt in der Linkliste eines Vorleseprogramms ein leerer Eintrag.

    KorrekturvergleichSchritt 2 · HTML

    Vorher

    <li><a href="/leistungen"><span aria-hidden="true">›</span></a></li>

    Nachher

    <li><a href="/leistungen">Leistungen</a></li>

    Markierte Zeilen wurden geändert

    So prüfen Sie es Öffnen Sie die Linkliste eines Vorleseprogramms. Jeder Menüpunkt trägt dort seinen Namen.

  3. Den Zustand beim Umschalten mitführen

    Sichtbarkeit und aria-expanded kommen aus derselben Entscheidung. So stimmt der angesagte Zustand immer mit dem sichtbaren Menü überein.

    KorrekturvergleichSchritt 3 · JavaScript

    Vorher

    schalter.addEventListener('click', () => {
      menue.classList.toggle('offen');
    });

    Nachher

    schalter.addEventListener('click', () => {
      const offen = menue.hasAttribute('hidden');
      menue.toggleAttribute('hidden', !offen);
      schalter.setAttribute('aria-expanded', String(offen));
    });

    Markierte Zeilen wurden geändert

    So prüfen Sie es Öffnen und schließen Sie das Menü. Ein Vorleseprogramm wechselt zwischen „erweitert“ und „reduziert“.

Werbung

Kostenloser Website-Barrierefreiheits-Check

Website auf Barrierefreiheit prüfen.

Technische WCAG-Warnsignale erkennen. Kritische Stellen zuerst prüfen.

Der Website-Check ist bereit.

Werbung

Ein letzter Schritt

Prüfen, bevor Sie gehen.

Finden Sie automatisch erkennbare Barrieren auf Ihrer eigenen Website.

Website prüfen

Kostenlos starten · keine Installation

Automatisches Screening. Tastaturbedienung und Screenreader bleiben manuelle Prüfung.