# An accessible cookie banner: keyboard, screen readers and WCAG 2.2

> An accessible cookie banner works with a screen reader and a keyboard, keeps focus visible, meets 4.5:1 contrast and 24-pixel targets. A WCAG 2.2 checklist.

Source: https://cookiequiet.com/guides/accessible-cookie-banner
Published: 2026-10-20
Publisher: Cookiequiet

## Steps

1. **Use semantic elements** Buttons for actions, a dialog role with aria-labelledby and aria-describedby for the container, switches with aria-checked for category toggles, a lang attribute matching the text.
2. **Make it keyboard operable** Every control reachable and usable with Tab, Enter and Space, in a logical order, with a visible focus ring. Trap focus only in a modal, and release it on close.
3. **Check contrast and size** 4.5:1 for button text, 3:1 for borders, focus rings and switch states, targets at least 24 by 24 pixels with spacing.
4. **Test zoom and small screens** At 200% text size and a 320 pixel viewport the banner must stay readable and operable without horizontal scrolling.
5. **Write parallel, plain labels** Accept all and Reject all as equal choices, a one-sentence explanation, real links to the policies, no countdown or auto-accept.
6. **Provide a way back** A keyboard-reachable Cookie settings link in the footer that opens the preferences centre.
7. **Test with assistive technology** Run through the banner with a screen reader and keyboard only, then with an automated checker, and fix what you find.

An accessible cookie banner is one that every visitor can understand and operate: with a keyboard alone, with a screen reader, at 200% zoom, on a small phone, with low vision or a tremor. Beyond being the right thing to do, it is part of consent being valid: a visitor who cannot reach the Reject button has not been offered a free choice. Since 28 June 2025 the European Accessibility Act (Directive (EU) 2019/882) applies to a range of online services, and the standard everyone measures against is WCAG 2.2, a W3C Recommendation since 5 October 2023 (the current edition is dated 12 December 2024). Here is the checklist, criterion by criterion.

## Structure and semantics

- **Use real buttons.** Accept all, Reject all and Customize are `<button>` elements, not styled `<div>`s. This satisfies 4.1.2 Name, Role, Value (Level A) for free: the role is button, the name is the text, and the state is exposed.
- **Give the dialog a name.** The banner container has `role="dialog"` (or `alertdialog`), `aria-labelledby` pointing at its heading and `aria-describedby` pointing at the explanatory text, following the WAI-ARIA Authoring Practices pattern for dialogs.
- **Mark the language.** The banner text is in the visitor's language, and the container carries a matching `lang` attribute when it differs from the page, so the screen reader switches voice (3.1.1 and 3.1.2).
- **Toggles are switches.** In the preferences centre, each category toggle has `role="switch"` with `aria-checked`, a visible label, and a description of what the category does. The necessary category is shown as always on and disabled, not hidden.

## Keyboard

- **Everything reachable.** Every control works with Tab, Shift+Tab, Enter and Space (2.1.1 Keyboard, Level A).
- **No trap unless modal.** A bar or floating box must not trap focus; a visitor can tab past it to the page (2.1.2 No Keyboard Trap, Level A). A centred modal that blocks the page may hold focus inside the dialog, following the modal dialog pattern, and must release it when the dialog closes.
- **Logical order.** Focus moves heading, text, Customize, Reject all, Accept all (or your chosen order), never jumping around (2.4.3 Focus Order, Level A).
- **Visible focus.** Each control shows a clear focus ring (2.4.7 Focus Visible, Level AA), and the focused control is not hidden behind the banner itself or another sticky element (2.4.11 Focus Not Obscured (Minimum), Level AA, new in 2.2). This matters when a bottom bar covers a focused link on the page.
- **Escape.** For a modal, Escape closes it without choosing, which is the same as not consenting yet; the page stays blocked until a choice is made only if you decided the banner is modal.
- **No surprise on focus.** Focusing a control must not trigger a change of context (3.2.1 On Focus, Level A): a toggle does not save and close when it receives focus.

## Visual design

- **Contrast.** Text on both buttons meets 4.5:1 against its background (1.4.3 Contrast (Minimum), Level AA); button borders, focus rings and switch states meet 3:1 (1.4.11 Non-text Contrast, Level AA). A grey Reject label on a light grey button fails this and also matches the "deceptive button contrast" practice the EDPB taskforce described in 2023.
- **Size.** Targets are at least 24 by 24 CSS pixels, with spacing between them (2.5.8 Target Size (Minimum), Level AA, new in 2.2). Make them larger on touch screens.
- **Zoom and reflow.** The banner remains usable at 200% text size (1.4.4 Resize Text, Level AA) and at a 320 CSS pixel wide viewport without horizontal scrolling (1.4.10 Reflow, Level AA). A bottom bar that grows to cover the whole phone screen at 200% is a common failure; let it become a modal or let it scroll.
- **Not colour alone.** The active state of a switch is shown by position or an icon, not only by colour (1.4.1 Use of Color, Level A).
- **Motion.** No animation that cannot be paused; respect `prefers-reduced-motion` for the entrance.

## Content

- **Plain words, short.** The first screen says what the banner is about, what the choices are and where to read more.
- **Equal wording.** Reject all and Accept all are parallel labels; nothing describes refusing as a loss.
- **Links are links.** "Cookie policy" and "Privacy policy" are real links with descriptive text.
- **No time limit.** The banner does not disappear or auto-accept after a delay (2.2.1 Timing Adjustable, Level A).

## Reopening the preferences

A visitor who used a screen reader to refuse should be able to find the settings later: a "Cookie settings" link in the footer, reachable by keyboard, that opens the preferences centre. The EDPB taskforce asks for an easily accessible way to withdraw, such as a permanently visible icon or a link in a visible, standardised place.

## Testing

1. Unplug the mouse. Tab through the banner and the preferences; operate every control; check the focus ring.
2. Turn on VoiceOver (macOS, iOS), NVDA (Windows) or TalkBack (Android); confirm the dialog is announced with its name, each button with its label, each switch with its state.
3. Zoom to 200% and resize the window to 320 pixels; check nothing is cut off.
4. Run a contrast checker on both buttons and the focus ring.
5. Run an automated checker (axe, Lighthouse) for the obvious errors, then fix the ones only a human finds.

## How Cookiequiet handles it

Cookiequiet's banner renders in a shadow root with real buttons, a labelled dialog, keyboard operation, visible focus, switches with states in the preferences centre, Accept all and Reject all at the same size and weight, 24 languages picked from the visitor's browser with every string editable, and three layouts (bar, floating box, centred modal) so you can choose non-modal or modal behaviour. Your brand colours are yours to set; check their contrast with the checker above before shipping.

## Questions

### Should the banner trap keyboard focus?

Only if it is a modal that blocks the page, and then following the modal dialog pattern: focus moves into the dialog, stays within it, and returns to the page when it closes. A bar or floating box must let the visitor tab past it.

### Is a bar at the bottom of the screen accessible?

It can be, if it does not cover focused elements on the page (WCAG 2.2 criterion 2.4.11) and stays usable at 200% zoom on a phone. If it grows to cover the screen, switch to a modal layout at small sizes or let it scroll.

### Does the European Accessibility Act apply to my website?

It applies to the products and services listed in Directive (EU) 2019/882, including e-commerce services, with obligations applying from 28 June 2025 and exemptions for microenterprises providing services. If the directive covers your service, your cookie banner is part of the interface it covers.

### Do I need to announce the banner when the page loads?

A labelled dialog is announced when it receives focus, or when a screen reader encounters it in reading order. For a non-modal bar, do not steal focus from the page content; make sure the banner is early in the reading order or exposed as a landmark the visitor can jump to.

## Sources

- [W3C, Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG22/)
- [W3C, WCAG 2.2 publication history](https://www.w3.org/standards/history/WCAG22/)
- [W3C WAI, ARIA Authoring Practices Guide: Dialog (Modal) pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)
- [Directive (EU) 2019/882 (European Accessibility Act)](https://eur-lex.europa.eu/eli/dir/2019/882/oj)
- [EDPB, Report of the work undertaken by the Cookie Banner Taskforce (PDF)](https://www.edpb.europa.eu/system/files/2023-01/edpb_20230118_report_cookie_banner_taskforce_en.pdf)
