Cookie-Banner barrierefrei gestalten: Checkliste für Consent-Dialoge

Foto: eine flache, gewellte Scheibe wie ein Keks neben einer runden Milchglasscheibe, die an einer aufrechten Glasplatte lehnt.

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 div gebaut sind.
  • Der Fokus ist unsichtbar, weil das Theme des Anbieters outline: none setzt.
  • „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.

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> oder role="dialog" mit aria-modal und 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-pressed beziehungsweise role="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.

Häufige Fragen

Muss ein Cookie-Banner barrierefrei sein?

Ja, wenn Ihre Website barrierefrei sein muss. Der Banner ist Teil jeder Seite, auf der er erscheint. Eine Barriere im Banner ist deshalb eine Barriere auf der ganzen Website, und WCAG bewertet ganze Seiten.

Ist es eine Tastaturfalle, wenn der Fokus im Banner bleibt?

Nicht, solange der Banner ein modaler Dialog ist, den man mit der Tastatur schließen kann – über eine Schaltfläche oder mit Escape. Dass der Fokus im offenen Dialog bleibt, ist dann richtig. Eine Falle entsteht, wenn es keinen Weg hinaus gibt.

Was soll passieren, wenn jemand den Banner mit Escape schließt?

Escape ist keine Einwilligung. Behandeln Sie es wie „Nur notwendige“ und speichern Sie diese Wahl, damit der Banner nicht bei jedem Seitenaufruf wiederkommt.

Wohin gehört der Fokus, wenn der Banner erscheint?

In den Dialog, und zwar nicht auf „Alle akzeptieren“. Gute Startpunkte sind die Überschrift des Dialogs oder die erste Schaltfläche nach dem erklärenden Text.

Reicht ein Cookie-Symbol zum erneuten Öffnen der Einstellungen?

Nur mit zugänglichem Namen, ausreichender Größe und ohne andere Inhalte zu verdecken. Robuster ist ein sichtbarer Text-Button „Cookie-Einstellungen“ im Footer.

Quellen

  1. W3C, Web Content Accessibility Guidelines (WCAG) 2.2 – https://www.w3.org/TR/WCAG22/
  2. W3C WAI-ARIA Authoring Practices Guide, Dialog (Modal) Pattern – https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
  3. MDN Web Docs, <dialog>: The Dialog element – https://developer.mozilla.org/docs/Web/HTML/Element/dialog
  4. W3C WAI-ARIA Authoring Practices Guide, Switch Pattern – https://www.w3.org/WAI/ARIA/apg/patterns/switch/
  5. Gesetz über den Datenschutz und den Schutz der Privatsphäre in der Telekommunikation und bei digitalen Diensten (TDDDG), § 25 – https://www.gesetze-im-internet.de/ttdsg/__25.html

Sehen Sie, was ein Scan auf Ihrer Website findet

Eine Seite in rund 30 Sekunden, ohne E-Mail. Der vollständige Bericht umfasst bis zu 100 Seiten und einen Tastatur-Durchlauf.