Kurz gesagt: Ein Cookie-Banner ist das erste Element, das jeder Besucher bedienen muss. Er muss per Tastatur erreichbar sein, einen sichtbaren Fokus haben, sich ohne Maus schließen lassen und alle Wahlmöglichkeiten gleich gut lesbar und bedienbar anbieten. Als modaler Dialog gehört er in ein <dialog>-Element mit Überschrift; als Leiste darf er nichts verdecken, was gerade den Fokus hat.
Cookie-Banner sind selten das Lieblingsthema einer Redaktion. Sie kommen von einem Consent-Anbieter oder einem Plugin, werden einmal eingerichtet und dann vergessen. Für Barrierefreiheit ist das riskant: Ein Banner, den man nicht mit der Tastatur erreicht oder nicht schließen kann, macht die gesamte Website unbenutzbar – egal wie sauber der Rest gebaut ist. Ob und wofür Sie eine Einwilligung brauchen, regeln die DSGVO und § 25 TDDDG. Dieser Beitrag behandelt nur, wie der Dialog barrierefrei wird.
Warum der Banner das wichtigste Element Ihrer Website ist
Der Banner erscheint auf der ersten Seite, die jemand öffnet, und bei vielen Lösungen liegt er über dem Inhalt, bis eine Wahl getroffen ist. Damit ist er Teil jeder Seite – und jede Barriere in ihm ist eine Barriere auf jeder Seite. WCAG bewertet ganze Seiten, nicht einzelne Komponenten: Eine Startseite mit einwandfreiem Inhalt, aber einem Banner ohne erreichbare Schaltflächen erfüllt die Kriterien nicht.
Die typischen Probleme sind immer dieselben:
- Die Schaltflächen sind mit Tab nicht erreichbar, weil der Banner am Ende des Quelltexts steht oder die Buttons als
divgebaut sind. - Der Fokus ist unsichtbar, weil das Theme des Anbieters
outline: nonesetzt. - „Nur notwendige“ ist ein hellgrauer Textlink neben einem großen farbigen „Alle akzeptieren“.
- Der Banner liegt als feste Leiste unten und verdeckt beim Tabben genau die Links, die gerade den Fokus haben.
- Das Symbol zum erneuten Öffnen ist ein Keks-Icon ohne Namen.
Dialog-Semantik und Fokus (dialog, aria-modal, Startfokus)
Entscheiden Sie zuerst, welche Art von Banner Sie haben:
- Modaler Dialog: Er blockiert die Seite, bis eine Wahl getroffen ist. Dann muss er sich auch für Hilfstechnik wie ein Dialog verhalten: Der Rest der Seite ist nicht erreichbar, der Fokus liegt im Dialog, und der Dialog hat einen Namen.
- Nicht modale Leiste: Die Seite bleibt benutzbar, der Banner ist ein zusätzlicher Bereich. Dann darf er den Fokus nicht festhalten, muss aber früh in der Tab-Reihenfolge erreichbar sein und darf nichts verdecken.
Für den modalen Fall ist das native <dialog>-Element die robusteste Grundlage. Mit showModal() macht der Browser den Rest der Seite inert, legt den Dialog in die oberste Ebene und setzt die Rolle dialog samt modalem Verhalten selbst.
<dialog id="consent" aria-labelledby="consent-title" aria-describedby="consent-text">
<h2 id="consent-title">Cookies und externe Inhalte</h2>
<p id="consent-text">
Wir nutzen notwendige Cookies, damit die Website funktioniert. Mit Ihrer
Einwilligung setzen wir außerdem Statistik-Cookies.
<a href="/datenschutz/">Datenschutzerklärung</a>
</p>
<div class="consent-actions">
<button type="button" data-choice="all">Alle akzeptieren</button>
<button type="button" data-choice="necessary">Nur notwendige</button>
<button type="button" data-choice="settings">Einstellungen</button>
</div>
</dialog>
const dialog = document.getElementById('consent')
if (!localStorage.getItem('consent')) dialog.showModal()
// Escape schließt einen modalen Dialog. Das ist keine Einwilligung:
// behandeln Sie es wie „Nur notwendige“.
dialog.addEventListener('cancel', () => saveChoice('necessary'))
saveChoice steht hier für Ihre eigene Funktion, die die Wahl speichert. Zum Startfokus: Der Browser setzt den Fokus beim Öffnen in den Dialog. Mit dem Attribut autofocus bestimmen Sie, wohin genau. Setzen Sie es nicht auf „Alle akzeptieren“ – wer mit Screenreader unterwegs ist, soll erst erfahren, worum es geht. Ein sinnvoller Start ist der erste Button nach dem Text oder die Überschrift selbst, wenn sie mit tabindex="-1" fokussierbar gemacht ist.
Wenn Ihr Anbieter kein natives <dialog> nutzt, muss sein Container role="dialog", aria-modal="true" und einen Namen über aria-labelledby haben, und der Rest der Seite muss für die Dauer des Dialogs unerreichbar sein. Das zuverlässig nachzubauen ist schwieriger, als es aussieht – ein Grund mehr, nach dem nativen Element zu fragen.
Tastatur: Tab-Reihenfolge, Escape, keine Falle
Ein Dialog, der den Fokus bei sich hält, ist keine Tastaturfalle. Eine Falle ist es erst, wenn man ihn mit der Tastatur nicht verlassen kann – weder über eine Schaltfläche noch mit Escape (2.1.2 Keine Tastaturfalle). Prüfen Sie deshalb:
- Mit Tab erreichen Sie jeden Link und jede Schaltfläche im Banner, in einer Reihenfolge, die dem Lesen entspricht.
- Mit Umschalt+Tab kommen Sie zurück.
- Enter und Leertaste lösen die Schaltflächen aus.
- Escape schließt einen modalen Dialog, ohne eine Einwilligung zu erteilen.
- Nach der Wahl landet der Fokus an einer sinnvollen Stelle, typischerweise am Anfang der Seite – nicht irgendwo in der Mitte.
Bei einer nicht modalen Leiste kommt eine Bedingung dazu: Sie muss am Anfang des Quelltexts stehen oder über einen Link am Seitenanfang erreichbar sein. Eine Leiste, die im Quelltext ganz unten steht, erreicht man erst nach Hunderten Tabs. Und sie darf beim Tabben keine fokussierten Elemente vollständig verdecken (2.4.11 Fokus nicht verdeckt). Mit scroll-padding-bottom in Höhe der Leiste auf dem html-Element scrollt der Browser fokussierte Elemente oberhalb der Leiste in den sichtbaren Bereich.
html { scroll-padding-bottom: 6rem; } /* Höhe der festen Consent-Leiste */
Gleichwertige Schaltflächen: Kontrast, Größe, Beschriftung
Aus Sicht der Barrierefreiheit gilt eine einfache Regel: Jede Wahl muss gleich gut wahrnehmbar und bedienbar sein. Konkret:
- Kontrast. Beschriftungen brauchen mindestens 4,5:1 gegenüber ihrem Hintergrund (1.4.3 Kontrast). Hellgrauer Text auf Weiß erreicht das selten. Prüfen Sie Ihre Farben mit unserem Kontrast-Checker.
- Größe. Klickflächen sollten mindestens 24 × 24 CSS-Pixel groß sein oder ausreichend Abstand haben (2.5.8 Zielgröße). Ein winziges „X“ in der Ecke scheitert oft daran.
- Beschriftung. „Alle akzeptieren“, „Nur notwendige“ und „Einstellungen“ sagen, was passiert. „OK“, „Weiter“ oder ein reines Icon sagen es nicht.
- Echte Buttons. Nur
<button>bringt Rolle, Fokus und Tastaturbedienung von Haus aus mit (4.1.2 Name, Rolle, Wert). - Sichtbarer Fokus. Jeder Button zeigt deutlich, wenn er den Fokus hat – auch auf dem Farbhintergrund des Banners.
Einstellungen, Kategorien und Schalter
Die zweite Ebene – Kategorien wie Statistik oder Marketing – ist oft schlechter gebaut als die erste. Schalter sind als div mit Klick-Handler umgesetzt, haben keinen Namen oder verraten ihren Zustand nicht. Eine robuste Lösung nutzt native Checkboxen, gruppiert in einem fieldset:
<fieldset>
<legend>Kategorien</legend>
<div class="consent-option">
<input type="checkbox" id="c-necessary" checked disabled aria-describedby="d-necessary">
<label for="c-necessary">Notwendig</label>
<p id="d-necessary">Immer aktiv. Speichert zum Beispiel Ihre Auswahl in diesem Dialog.</p>
</div>
<div class="consent-option">
<input type="checkbox" role="switch" id="c-stats" aria-describedby="d-stats">
<label for="c-stats">Statistik</label>
<p id="d-stats">Hilft uns zu verstehen, welche Seiten genutzt werden.</p>
</div>
</fieldset>
<button type="button" data-choice="save">Auswahl speichern</button>
role="switch" lässt Screenreader „Schalter, aus“ statt „Kontrollkästchen, nicht aktiviert“ ansagen; die Leertaste schaltet ihn wie jede Checkbox. Die Beschreibung ist über aria-describedby mit dem Schalter verbunden. Eine lange Liste einzelner Dienste lässt sich mit <details> und <summary> aufklappbar machen, ohne eigenes Skript. Und bitte: kein Speichern beim bloßen Umschalten, das den Dialog überraschend schließt.
Der Button zum erneuten Öffnen
Wer eine Einwilligung gegeben hat, muss sie ändern können. Viele Anbieter blenden dafür ein schwebendes Symbol ein – oft ein Keks oder ein Fingerabdruck in einer Ecke. Drei Dinge gehen dabei häufig schief:
- Das Symbol hat keinen zugänglichen Namen. Ein Screenreader liest „Schalter“ und sonst nichts.
- Es verdeckt Inhalte, etwa den Warenkorb-Button in der mobilen Ansicht.
- Es sitzt am Ende der Tab-Reihenfolge und ist praktisch nicht auffindbar.
Besser ist ein sichtbarer Text-Button im Footer, der den Dialog wieder öffnet:
<footer>
…
<button type="button" class="link-button" id="consent-open">Cookie-Einstellungen</button>
</footer>
document.getElementById('consent-open').addEventListener('click', () => dialog.showModal())
Wenn es zusätzlich ein schwebendes Symbol gibt, braucht es mindestens ein aria-label="Cookie-Einstellungen" und darf keine anderen Bedienelemente überdecken.
Fragen an Ihren Consent-Anbieter
Die meisten Websites bauen den Banner nicht selbst, sondern nutzen ein Tool – ob Borlabs Cookie, Usercentrics, Cookiebot oder ein anderes. Diese Fragen sollte Ihr Anbieter beantworten können, bevor Sie Zeit in eigene Workarounds stecken:
- Nutzt der Dialog ein natives
<dialog>oderrole="dialog"mitaria-modalund einer Überschrift als Namen? - Wohin setzt er den Fokus beim Öffnen, und wohin nach dem Schließen?
- Lässt er sich mit Escape schließen, und was wird dabei gespeichert?
- Sind alle Schaltflächen echte Buttons mit sichtbarem Fokus?
- Lassen sich Farben und Größen so anpassen, dass alle Schaltflächen 4,5:1 Kontrast und 24 Pixel Zielgröße erreichen?
- Sind die Schalter in den Einstellungen native Checkboxen oder Buttons mit
aria-pressedbeziehungsweiserole="switch"? - Gibt es eine Möglichkeit, den Dialog über einen eigenen Link im Footer zu öffnen?
- Hat der Anbieter selbst einen Prüfbericht zur Barrierefreiheit des Dialogs, und gegen welche WCAG-Fassung?
Antworten, die nur „ist barrierefrei“ lauten, sind keine Antworten. Bitten Sie um den Bericht.
Was Reviseberg dabei prüft – und was nicht
Reviseberg klickt beim Crawlen nichts an. Es sieht Ihre Website deshalb so wie jemand, der zum ersten Mal kommt: mit geöffnetem Banner. Die axe-core-Regeln laufen auf der Seite mitsamt Banner, bei 1280 Pixeln Breite und für die layoutabhängigen Regeln – Kontrast, Zielgröße – noch einmal bei 360 Pixeln. Fehlende Namen, zu geringer Kontrast und zu kleine Ziele im Banner tauchen deshalb in den Ergebnissen auf.
Der Tastatur-Agent drückt auf der Seite, die Sie als Startseite angeben, Tab, Umschalt+Tab und Escape. Er zeigt, ob der Banner erreichbar ist, ob der Fokus auf seinen Schaltflächen sichtbar ist und ob man irgendwo festhängt – wobei er Fokus, der in einem modalen Dialog bleibt, bewusst nicht als Falle meldet. Zusätzlich führt Reviseberg auf, welche Cookies beim Laden gesetzt und welche fremden Hosts angefragt wurden, bevor jemand den Banner bedienen konnte. Eine rechtliche Bewertung ist das nicht.
Was Reviseberg nicht tut: Es öffnet weder die Einstellungen des Banners noch prüft es, was eine Wahl bewirkt – der Tastatur-Agent trifft die datensparsamste Wahl nur, in einem eigenen Browser, um die Seite dahinter abzugehen. Diese Schritte testen Sie von Hand mit der Checkliste oben. Mehr zum Agenten steht unter Tastatur-Agent, alle Prüfungen auf der Plattform-Seite. Für WordPress-Seiten mit Consent-Plugins hilft zusätzlich unser Leitfaden zu WordPress.