Cookie banner
A cookie banner that doesn't steal focus or get in the way, closes with Escape, and lets you change your choice any time. No plugin, no cookies before consent.
Demo
The banner at the bottom is the live demo. Nothing is sent to a server: the choice stays in your browser only. “Show the banner again” returns it to the first-visit state at any time.
Why it is accessible
A cookie banner is often the first thing a visitor meets on a website, and it's also the part most often got wrong. Plugins tend to render it as a modal window that grabs keyboard focus, covers the content, can only be closed by giving consent, and vanishes for good once it's closed. This banner does the exact opposite.
Focus order. The banner is a region, with its own heading, not a dialog. Once the page loads it sits right after the skip links, so a keyboard user reaches it after a few presses of Tab, but nothing forces focus onto it. The whole page stays usable even before a decision is made.
It can always be closed. The "Accept all" and "Reject non-essential" buttons look alike and sit equally close together; rejecting is exactly as easy as accepting. Escape closes the banner and counts as rejection. While the banner is showing, its height is written into the document's scroll-padding, so no focused element is ever left hidden behind it.
Changing your mind later. The "Change cookie settings" button can live anywhere, typically in the footer; it opens the banner with the current choice already set, and closing it returns focus to wherever the user came from. The choice is stored with a version number: when a new category is added, we ask again.
Until the user decides, nothing beyond the essential is stored, and remembering a rejection needs no cookie at all. This website doesn't use cookies at all; the banner below is a demonstration.
Test it yourself
Keyboard
- Reload the page: focus stays at the start of the page; the banner doesn't steal it.
- Tab three times past the skip links and you're in the banner: Accept, Reject, Settings.
- Escape inside the banner closes it; Tab after that continues normally into the header.
- The "Change cookie settings" button opens the banner with the categories expanded; Escape returns focus to the button.
Screen reader
- On loading you hear a polite announcement that the site uses cookies and where the banner is.
- The regions list includes "Cookies on this website"; the Settings button announces expanded / collapsed.
- After you choose, you hear the status message "Cookie settings saved: …".
Zoom and reflow
- At 400% zoom the banner scrolls inside itself, the buttons stack vertically, and the page content behind it stays reachable.
Without JavaScript
The banner isn't shown. Without scripts, nothing that would need consent loads either, so there's nothing to resolve. The buttons for changing settings are hidden.
Code to copy
<ad-consent data-version="1">
<section class="consent" role="region" aria-labelledby="consent-title" hidden>
<h2 id="consent-title" tabindex="-1">Cookies on this website</h2>
<p>Essential cookies keep the site working. …</p>
<form>
<div class="consent__actions">
<button type="button" class="button" data-consent="accept">Accept all</button>
<button type="button" class="button" data-consent="reject">Reject non-essential</button>
<button type="button" class="button button--ghost" data-consent="settings" aria-expanded="false" aria-controls="consent-settings">Settings</button>
</div>
<fieldset id="consent-settings" hidden>
<legend>Cookie categories</legend>
<label><input type="checkbox" checked disabled> Essential</label>
<label><input type="checkbox" name="analytics"> Analytics</label>
<button type="submit" class="button" data-consent="save">Save choices</button>
</fieldset>
</form>
</section>
</ad-consent>
<button type="button" data-consent-open>Change cookie settings</button>
<link rel="stylesheet" href="/assets/js/components/ad-consent/ad-consent.css">
<script type="module" src="/assets/js/components/ad-consent/ad-consent.js"></script>