Why Accessibility Matters for Consent Banners
Cookie consent banners are, by definition, shown to every visitor before they can access your site. That makes them the most universally accessed UI element on your site — and the one most likely to exclude users with disabilities if implemented poorly.
Under the UK Equality Act 2010 and equivalent EU legislation, inaccessible web content can constitute unlawful discrimination. Combine that with GDPR's requirement for freely-given consent, and an inaccessible banner could invalidate your consent records entirely.
The WCAG 2.1 AA Checklist for Consent UIs
1. Keyboard Navigation (2.1.1 — Level A)
Every interactive element in your consent banner must be reachable and operable via keyboard alone:
<!-- Bad: click-only dismiss -->
<div onclick="dismissBanner()">✕</div>
<!-- Good: focusable, keyboard-operable -->
<button type="button" onclick="dismissBanner()" aria-label="Close consent banner">
<span aria-hidden="true">✕</span>
</button>
Tab order must be logical. When the banner appears, focus should move into it. When dismissed, focus should return to the triggering element or a sensible position in the page.
2. Focus Management
When your consent modal opens, trap focus within it:
function trapFocus(element) {
const focusableElements = element.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const first = focusableElements[0];
const last = focusableElements[focusableElements.length - 1];
element.addEventListener('keydown', (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
if (document.activeElement === first) {
last.focus();
e.preventDefault();
}
} else {
if (document.activeElement === last) {
first.focus();
e.preventDefault();
}
}
});
first.focus();
}
3. ARIA Roles and Labels (4.1.2 — Level A)
Your consent dialog must be announced to screen readers:
<div
role="dialog"
aria-modal="true"
aria-labelledby="consent-title"
aria-describedby="consent-description"
>
<h2 id="consent-title">Cookie Preferences</h2>
<p id="consent-description">
We use cookies to improve your experience. Choose which categories you accept.
</p>
<!-- toggles and buttons -->
</div>
4. Colour Contrast (1.4.3 — Level AA)
Text must meet a minimum contrast ratio of 4.5:1 for normal text, 3:1 for large text. Common failures:
- Grey text on white background for "less important" decline options (dark pattern)
- Light blue "Accept" button with white text
Use the WebAIM Contrast Checker or axe DevTools to verify.
5. Toggle Switches
Category toggles are common in preference centres. Ensure they're accessible:
<label class="toggle-label">
<input
type="checkbox"
role="switch"
aria-checked="false"
id="analytics-toggle"
/>
<span class="toggle-track" aria-hidden="true"></span>
<span class="toggle-label-text">Analytics cookies</span>
</label>
Note: role="switch" communicates the on/off nature to screen readers. Always pair with a visible label.
Dark Patterns to Avoid
The ICO and EDPB have both issued guidance on consent dark patterns. Avoid:
- Asymmetric friction — "Accept All" is a big colourful button, "Reject All" is buried in settings
- Pre-ticked boxes — categories pre-selected as "on" by default
- Misleading language — "I agree to a better experience" instead of "Accept marketing cookies"
- Endless clicks to decline — users should be able to decline in as few clicks as it takes to accept
Testing Your Banner
Tools to test consent UI accessibility:
- axe DevTools (browser extension) — automated WCAG scanning
- NVDA + Firefox (free screen reader) — test the full keyboard/screen reader flow
- VoiceOver + Safari (macOS/iOS) — test Apple's screen reader
- Keyboard-only test — unplug your mouse and try to use the banner
DPOKit's Approach
DPOKit's consent banner is built to WCAG 2.1 AA out of the box:
- Focus is trapped in the modal and restored on close
- All interactive elements are keyboard-operable
- ARIA roles, labels, and live regions are correctly applied
- Reject All is presented with equal visual prominence to Accept All
- All default colour combinations meet 4.5:1 contrast ratio
Custom CSS is fully supported — but be aware that overriding styles can break accessibility compliance. Test after any theme customisation.
James Okafor
Frontend Engineer