Mega-Menü Schritt für Schritt: HTML, CSS und JavaScript mit Barrierefreiheit
Wie Sie ein Mega-Menü bauen: HTML-, CSS- und JavaScript-Code zum Kopieren, Bedienung per Tastatur und Screenreader, Smartphone-Version, häufige Fehler und Demo.
Ein Mega-Menü ist ein großes Panel, das sich aus dem oberen Menü aufklappt und mehrere Gruppen von Links auf einmal zeigt, oft mit kurzen Beschreibungen. Sie kennen es aus Onlineshops und von Websites von Firmen mit umfangreichem Angebot. Gut gemacht, verkürzt es den Weg zu einer bestimmten Leistung. Schlecht gemacht, schließt es sich, bevor der Mauszeiger es erreicht, funktioniert auf dem Smartphone nicht und lässt sich nicht per Tastatur bedienen.
In diesem Ratgeber bauen wir ein Mega-Menü von Grund auf: HTML, CSS und etwa 30 Zeilen JavaScript, ganz ohne Bibliothek. Den Code habe ich im Browser geprüft, und das funktionierende Demo öffnen Sie hier. Dasselbe Muster läuft in meinem eigenen Menü: dem Button „Kostenlose Tools“ oben auf dieser Seite.
Wann ein Mega-Menü sinnvoll ist
Ein Mega-Menü ist nützlich, wenn:
- Sie in einem Teil des Angebots mehr als 7–8 Unterseiten haben, zum Beispiel mehrere Arten von Leistungen in mehreren Gruppen,
- sich das Angebot natürlich in Kategorien gliedert (Onlineshop, Baufirma, Buchhaltungsbüro mit Leistungen für verschiedene Kundengruppen),
- Sie neben den Links eine kurze Beschreibung oder einen hervorgehobenen Call-to-Action zeigen möchten.
Hat die ganze Website nur 5–6 Unterseiten, genügt ein gewöhnliches Menü. Ein Mega-Menü mit drei Links wirkt leer und macht den Code nur länger.
Wie ein gutes Mega-Menü funktionieren soll
Legen Sie die Regeln fest, bevor Sie Code schreiben. Jede davon hat ihren Grund:
- Es öffnet sich per Klick, und per Tastatur mit Enter oder der Leertaste. Das bloße Überfahren mit der Maus funktioniert auf dem Smartphone nicht.
- Es schließt sich bei einem Klick daneben, mit der Escape-Taste und dann, wenn Sie mit der Tab-Taste weitergehen.
- Der Screenreader weiß, ob das Panel aufgeklappt ist, dank des Attributs
aria-expanded. - Die Links sind gewöhnliche
<a>-Tags im HTML, damit Google alle Unterseiten sieht. - Zwischen Button und Panel gibt es keine Lücke, in der der Mauszeiger das Menü „verliert“.
- Auf dem Smartphone wird das Panel zu einer Dropdown-Liste unter dem Button „Menu“.
- Die Gruppen haben Überschriften, und das ganze Panel hat höchstens einen hervorgehobenen Call-to-Action.

Schritt 1: HTML
Jeder aufklappbare Eintrag besteht aus einem Button und einem Panel. Ein Button und kein Link, weil er nichts unter einer neuen Adresse öffnet, sondern nur das Panel zeigt. Das Attribut aria-controls verweist auf das Panel, und hidden blendet es am Anfang aus:
<header class="top">
<div class="top__in">
<a class="logo" href="/">Pomost</a>
<button class="burger" type="button" aria-expanded="false" aria-controls="menu">Menu</button>
<nav class="nav" id="menu" aria-label="Menu główne">
<ul class="nav__list">
<li>
<button class="nav__toggle" type="button" aria-expanded="false" aria-controls="mm-oferta">Oferta</button>
<div class="mega" id="mm-oferta" hidden>
<div class="mega__in">
<div>
<p class="mega__title" id="mm-tarasy">Tarasy</p>
<ul aria-labelledby="mm-tarasy">
<li><a href="/tarasy-kompozytowe">Tarasy kompozytowe<small>Bez malowania, na lata</small></a></li>
<li><a href="/tarasy-drewniane">Tarasy drewniane<small>Modrzew, sosna, egzotyki</small></a></li>
</ul>
</div>
<!-- weitere Spalten: Gärten, Zubehör -->
<div class="mega__promo">
<b>Bezpłatny pomiar</b>
<p>Przyjedziemy, zmierzymy i w 2 dni prześlemy wycenę.</p>
<a href="/kontakt">Umów pomiar</a>
</div>
</div>
</div>
</li>
<li><a href="/realizacje">Realizacje</a></li>
<li><a href="/kontakt">Kontakt</a></li>
</ul>
</nav>
</div>
</header>
Die Überschrift einer Gruppe ist ein gewöhnlicher Absatz, und die Liste ist über aria-labelledby mit ihr verbunden. Der Screenreader liest dann „Tarasy, Liste, 3 Einträge“ vor, und in der Überschriftenstruktur der Seite tauchen nicht plötzlich mehr als ein Dutzend zusätzliche H2 auf.
Häufig sehe ich in solchen Menüs role="menu" und role="menuitem". Das ist ein Fehler: Diese Rollen sind für Anwendungsmenüs gedacht (wie „Datei, Bearbeiten“ in einem Editor) und versprechen eine Bedienung mit den Pfeiltasten, die eine gewöhnliche Website nicht bietet. Für die Navigation empfehlen die WAI-ARIA Authoring Practices genau das Muster „Disclosure“, also einen Button, der Inhalte ein- und ausblendet.
Schritt 2: CSS
Am wichtigsten sind drei Dinge: Das Panel schließt ohne Lücke an den Header an, das Aussehen des Buttons hängt von aria-expanded ab, und der Tastaturfokus ist gut sichtbar:
.top { position: relative; background: #fff; }
.nav__list { display: flex; gap: 4px; margin: 0; padding: 0; list-style: none; }
.nav__toggle { display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px;
border: 0; border-radius: 10px; background: none; font: inherit; cursor: pointer; }
/* Der Pfeil dreht sich, wenn das Panel geöffnet ist: Der Zustand wird direkt aus aria-expanded gelesen */
.nav__toggle::after { content: ""; width: 7px; height: 7px; border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .2s; }
.nav__toggle[aria-expanded="true"]::after { transform: translateY(1px) rotate(-135deg); }
/* Panel über die volle Breite, beginnt genau unter dem Header (top: 100%, ohne Außenabstand) */
.mega { position: absolute; left: 0; right: 0; top: 100%; z-index: 10; background: #fff;
box-shadow: 0 24px 40px -24px rgba(17, 21, 28, .25); }
.mega__in { max-width: 1120px; margin: 0 auto; padding: 28px 20px 32px;
display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, 1.2fr); gap: 32px; }
.mega ul { margin: 0; padding: 0; list-style: none; }
.mega ul a { display: block; padding: 8px 10px; border-radius: 10px; text-decoration: none; }
.mega ul small { display: block; color: #5b6472; font-size: 13.5px; }
:focus-visible { outline: 3px solid #2f5bff; outline-offset: 2px; }
/* kurzes Einblenden des Panels, aber nicht für Personen, die Animationen im System abgeschaltet haben */
@media (prefers-reduced-motion: no-preference) {
.mega:not([hidden]) { animation: wjazd .18s ease-out; }
}
@keyframes wjazd { from { opacity: 0; transform: translateY(-6px); } }
Beachten Sie minmax(0, 1fr) im Raster. Ohne das kann ein langes Wort in einer Spalte das Panel breiter machen als den Bildschirm.
Schritt 3: JavaScript
Das Skript tut vier Dinge: Es öffnet und schließt das Panel per Klick, schließt andere Panels, reagiert auf Escape und schließt das Menü, wenn Sie daneben klicken oder mit der Tab-Taste aus dem Menü hinausgehen:
const nav = document.querySelector('.nav');
const toggles = [...nav.querySelectorAll('.nav__toggle')];
function setOpen(btn, open) {
btn.setAttribute('aria-expanded', String(open));
document.getElementById(btn.getAttribute('aria-controls')).hidden = !open;
}
function closeAll(except) {
toggles.forEach((b) => { if (b !== except) setOpen(b, false); });
}
toggles.forEach((btn) => btn.addEventListener('click', () => {
const open = btn.getAttribute('aria-expanded') !== 'true';
closeAll(btn);
setOpen(btn, open);
}));
// Escape schließt das geöffnete Panel und springt zurück zu seinem Button
nav.addEventListener('keydown', (e) => {
const btn = toggles.find((b) => b.getAttribute('aria-expanded') === 'true');
if (e.key === 'Escape' && btn) { setOpen(btn, false); btn.focus(); }
});
// Ein Klick außerhalb des Menüs und ein Fokuswechsel auf ein Element außerhalb des Menüs schließen das Panel
document.addEventListener('click', (e) => { if (!nav.contains(e.target)) closeAll(); });
document.addEventListener('focusin', (e) => { if (!nav.contains(e.target)) closeAll(); });
Der Zustand des Menüs ist an einer einzigen Stelle gespeichert: in den Attributen aria-expanded und hidden. Das CSS liest ihn, um den Pfeil zu drehen, der Screenreader, um „aufgeklappt“ und „eingeklappt“ anzusagen, und das Skript, um zu entscheiden, was geschlossen wird. Es gibt keine separaten Klassen wie is-open, die von dem abweichen könnten, was eine blinde Person hört.
Eine Beobachtung aus den Tests: Die erste Version schloss das Menü im Ereignis focusout. Das funktionierte per Tastatur, aber das Panel verschwand beim Klick auf seinen Hintergrund, weil der Browser dann den Fokus vom Button nimmt. Das Ereignis focusin auf dem ganzen Dokument reagiert nur, wenn der Fokus tatsächlich auf ein anderes Element wechselt, und hat dieses Problem nicht.
Schritt 4: Version für das Smartphone
Auf dem Smartphone ist kein Platz für vier Spalten. Denselben HTML-Code verwandeln wir in eine Dropdown-Liste: Die Navigation verschwindet hinter dem Button „Menu“, und die Panels ordnen sich untereinander an:
.burger { display: none; }
@media (max-width: 860px) {
.burger { display: inline-flex; margin-left: auto; padding: 10px 14px;
border: 1px solid #e3e6eb; border-radius: 10px; background: none; font: inherit; }
.nav { display: none; position: absolute; left: 0; right: 0; top: 100%; z-index: 10;
max-height: calc(100dvh - 68px); overflow-y: auto; background: #fff; }
.nav.is-open { display: block; }
.nav__list { flex-direction: column; padding: 8px 12px 16px; }
.nav__toggle { width: 100%; justify-content: space-between; padding: 14px 12px; }
.mega { position: static; box-shadow: none; }
.mega__in { grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 8px 12px 16px; }
}
const burger = document.querySelector('.burger');
burger.addEventListener('click', () => {
const open = burger.getAttribute('aria-expanded') !== 'true';
burger.setAttribute('aria-expanded', String(open));
nav.classList.toggle('is-open', open);
});
max-height mit der Einheit dvh und overflow-y: auto sorgen dafür, dass sich ein langes Menü auf einem kleinen Bildschirm scrollen lässt und die Adressleiste des Browsers auf dem Smartphone es nicht verdeckt.

So testen Sie das Menü in 5 Minuten
Bevor Sie das Menü veröffentlichen, prüfen Sie es so, wie Menschen es nutzen werden:
- Tastatur: Gehen Sie mit der Tab-Taste zu „Oferta“ (Angebot), Enter öffnet das Panel, weitere Tabs führen durch die Links, Escape schließt das Panel und kehrt zum Button zurück. Ein Tab nach dem letzten Link schließt das Panel.
- Maus: Fahren Sie mit dem Mauszeiger diagonal vom Button zum Panel und klicken Sie auf eine leere Stelle im Panel. Das Panel soll geöffnet bleiben.
- Screenreader: In NVDA (Windows) oder VoiceOver (Mac, iPhone) sollte der Button „Oferta, Schaltfläche, eingeklappt“ lauten und nach dem Öffnen „ausgeklappt“.
- Smartphone und Vergrößerung: Bei 320 px Breite und 200 % Vergrößerung darf nichts über den Bildschirm hinausragen oder seitliches Scrollen erzwingen.
- Lighthouse in Chrome (Registerkarte „Barrierefreiheit“) deckt fehlende Namen von Buttons und zu schwachen Kontrast auf.
Den allgemeinen Zustand Ihrer Website, einschließlich Barrierefreiheit, SEO und Geschwindigkeit, prüfen Sie in 30 Sekunden mit meinem Tool Website prüfen.
Die häufigsten Fehler beim Mega-Menü
- Menü nur beim Überfahren. Auf dem Smartphone lässt es sich nicht öffnen, und am Computer öffnet es sich versehentlich.
- Lücke zwischen Button und Panel. Schon
margin-top: 8pxgenügt, damit der Mauszeiger auf dem Weg zum Panel das Menü verlässt und sich alles schließt. <a href="#">statt eines Buttons. Die Seite springt nach oben, und der Screenreader kündigt einen Link an, der nirgendwohin führt.role="menu"ohne Bedienung mit den Pfeiltasten. Ein Versprechen, das die Seite nicht einhält, ist schlimmer als gar kein ARIA.- Links, die erst beim Überfahren per Skript nachgeladen werden. Google sieht sie womöglich nicht.
- Zu viele Links. Ein Panel mit 120 Einträgen ist ein Katalog, keine Navigation. Die Suche dauert 2–3 Sekunden, und wer nichts findet, geht zurück zu Google.
- Panel breiter als der Bildschirm auf dem Smartphone. Das klassische Symptom: Die Seite lässt sich um einige Pixel zur Seite verschieben.
Und WordPress?
In WordPress stammt das Mega-Menü meist vom Theme oder von einem Plugin. Bevor Sie es behalten, gehen Sie dieselbe Testliste durch: Viele Plugins öffnen das Menü nur beim Überfahren, setzen kein aria-expanded und laden auf jeder Unterseite einige Dutzend Kilobyte Skripte zusätzlich. Manchmal ist es einfacher und schneller, ein eigenes Menü auf Basis des Codes aus diesem Ratgeber zu ergänzen.
Zusammenfassung
Ein gutes Mega-Menü besteht aus einem Button mit aria-expanded, einem Panel mit hidden, gewöhnlichen Links im HTML und drei Wegen zum Schließen: Klick daneben, Escape und Tab. Auf dem Smartphone funktioniert derselbe Code als Dropdown-Liste. Den vollständigen Code aus diesem Artikel finden Sie im Demo: Öffnen Sie es, probieren Sie es mit Maus und Tastatur aus und sehen Sie sich dann den Quelltext der Seite an.
Wenn Ihre Website ein umfangreiches Angebot hat und das Menü nicht mithält, schreiben Sie mir. Ich baue die Navigation Ihrer bestehenden Website um oder entwerfe eine neue Firmenwebsite. Ich antworte in 24 Stunden, und Neukunden erhalten 20 % Rabatt auf den ersten Auftrag.
Häufige Fragen
Nein, wenn die Links im normalen HTML-Code der Seite stehen und nicht erst beim Überfahren mit der Maus nachgeladen werden. Google sieht dann alle Unterseiten. Übertreiben Sie es aber nicht mit der Zahl der Links: Ein Dutzend gut benannter Einträge hilft, mehrere Hundert verwässern das Signal, welche Unterseiten am wichtigsten sind.
Besser per Klick. Das Überfahren funktioniert auf Touchscreens nicht, und am Computer öffnet sich das Menü versehentlich, wenn der Mauszeiger nur über den Header wandert. Wenn Ihnen das Überfahren wichtig ist, fügen Sie eine Verzögerung von etwa 200 ms hinzu und lassen Sie den Klick als Hauptweg zum Öffnen bestehen.
Die Rolle menu ist für Anwendungsmenüs gedacht, etwa „Datei, Bearbeiten“ in einem Texteditor, und verlangt Bedienung mit den Pfeiltasten. Für die Navigation einer Website empfehlen die WAI-ARIA-Richtlinien ein einfacheres Muster: eine Schaltfläche mit aria-expanded, die eine Liste normaler Links ein- und ausblendet.
Eine gute Faustregel sind 3–4 Spalten mit je 3–8 Links. Brauchen Sie mehr, ist das ein Zeichen, dass Sie Ihr Angebot ordnen oder eine Kategorieseite ergänzen sollten, zu der das Menü führt.
Passende Leistungen
Haben Sie ein ähnliches Projekt?
Beschreiben Sie, was Sie brauchen, und Sie erhalten innerhalb von 24 Stunden ein Angebot. Neukunden erhalten 20 % Rabatt auf den ersten Auftrag.


