Skip to main content
Back to Guides
Customization7 min read

Keyboard Focus in Cookie Banners

Focus is the keyboard user's cursor, and cookie banners keep losing it: no focus on open, a trap with no exit, or a sticky bar hiding the very field the user just tabbed to. Here's how to get focus right.

Focus is the keyboard user's cursor, and banners keep losing it

A keyboard user doesn't point at things, they move a focus ring from element to element with Tab. If your banner never puts focus where it should, traps it with no way out, or lets a sticky bar cover the element that has focus, that user is stuck. This isn't rare hardware. It's anyone using a keyboard, a switch device, or a screen reader, which is most screen-reader users. Focus is also where good and bad banners diverge, because getting it right takes deliberate handling that's easy to skip.

The general accessibility picture is in Cookie Banner Accessibility. This guide goes deep on one thing: focus.

Modal or not? Decide that first

Your focus rules depend on one architectural choice. Is the banner modal, blocking the page until the visitor answers, or non-modal, a bar the visitor can ignore while they use the site? Both can be compliant, but they have opposite focus behaviour, and the worst banners are the ones that can't decide, trapping focus sometimes and leaking it other times.

  • Modal: expose it as a dialog with role="dialog" and aria-modal="true", name it with aria-labelledby, move focus in, and trap focus until the visitor chooses.
  • Non-modal: it's a region of the page. Don't trap focus. Make it reachable in the normal tab order and clearly labelled.

Pick one deliberately and build for it. The WAI-ARIA modal dialog pattern is the reference for the modal case.

Modal banners: move focus in, trap it, send it back

A modal consent dialog needs three moves, in order:

  • Move focus in on open. When the dialog appears, send focus to an element inside it, usually the heading (with tabindex="-1") or the first control. This is what tells a screen reader the dialog exists. A modal that opens with focus still out on the page behind it is silent to the people who most need to know it's there.
  • Trap focus while it's open. Tab and Shift+Tab should cycle through the dialog's controls and wrap around, never landing on the page behind. To make the background truly inert, the modern approach is the inert attribute on everything outside the dialog, which removes it from focus and the accessibility tree in one step.
  • Return focus on close. When the visitor makes a choice and the dialog closes, send focus back to a sensible place, typically the control that opened it, or the top of the page if the banner opened on load. Don't drop focus back to the top of the document silently.
// Sketch of the three moves for a modal consent dialog
function openConsentDialog(dialog, opener) {
  // 1. background inert so Tab can't reach it
  document.querySelectorAll('body > :not(.cb-dialog-root)')
    .forEach(el => el.inert = true);

  // 2. move focus in (heading has tabindex="-1")
  dialog.querySelector('.cb-title').focus();

  dialog.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') closeConsentDialog(dialog, opener);
    // Tab wrap handled here, or rely on inert + a focus sentinel
  });
}

function closeConsentDialog(dialog, opener) {
  document.querySelectorAll('body > :not(.cb-dialog-root)')
    .forEach(el => el.inert = false);
  opener ? opener.focus() : document.body.focus(); // 3. return focus
}
Copy code to clipboard

Escape should do something, and it shouldn't mean "yes"

The dialog pattern says Escape closes the dialog, and keyboard users expect it. But a consent banner has a twist worth thinking through: closing must never quietly count as acceptance. If Escape (or an X in the corner) dismisses the banner and you treat that as consent, you've recorded agreement the visitor never gave, which isn't valid consent and edges into dark-pattern territory. Two clean options: treat Escape and dismiss as "reject non-essential," or don't offer a bare close at all and require an explicit choice. What you can't do is make dismissal mean acceptance. Whatever you pick, be consistent so keyboard and screen-reader users can predict what a key does.

Non-modal bars: reachable, not a trap

If your banner is a bar the visitor can use the site around, don't trap focus in it. Trapping focus in a non-modal element is its own failure, the visitor can't Tab out to the page. Instead, expose the bar as a labelled region, put its controls in the natural tab order, and let focus flow through. The tradeoff is that a visitor might tab past the bar into the page without answering, which is fine for a non-modal design as long as no non-essential tracking runs until they do choose.

The WCAG 2.2 Trap Nobody Designed For

WCAG 2.2 added Focus Not Obscured (Minimum), Success Criterion 2.4.11, and the W3C's own explanation names cookie banners as a cause of failure. Here's the scenario: a sticky bar pinned to the bottom of the viewport, and a keyboard user tabbing down a form. Focus lands on a field that sits behind the bar, so the visitor can't see where they are. The W3C states a sticky cookie banner fails this criterion if it entirely hides a component receiving focus (failure technique F110). A modal banner that blocks the page is fine. A persistent bar that overlaps focusable content below it is the problem. Either reserve space so content never scrolls under the bar, or make sure a focused element is scrolled into the clear.

Make the focus ring impossible to miss

None of this helps if a keyboard user can't see where focus is. Never remove the focus outline without replacing it with something at least as visible, the bare outline: none is one of the most common accessibility regressions on the web. Every control in the banner, accept, reject, each toggle, the close, needs a focus indicator that stands out against its background, at 3:1 contrast against adjacent colours. WCAG 2.2's Focus Appearance criterion pushes further on how big and contrasty that indicator should be. A visible, high-contrast focus ring is what turns "technically operable by keyboard" into "actually usable."

Cookie banner focus checklist

  • Decide modal vs non-modal, and build for it consistently

    Opposite focus rules; don't half-trap focus.

  • Modal: move focus into the dialog on open

    role=dialog, aria-modal, aria-labelledby, focus to heading or first control.

  • Modal: trap focus with inert on the background

    Tab and Shift+Tab cycle inside and wrap, never reaching the page.

  • Return focus to the opener when the dialog closes

    Don't drop focus silently to the top of the document.

  • Handle Escape, and never treat dismissal as acceptance

    Escape or X means reject non-essential, or require an explicit choice.

  • Non-modal bars: reachable in tab order, no focus trap

    Let focus flow through; gate tracking until the visitor chooses.

  • Keep a sticky bar from hiding focused content below it

    WCAG 2.2 Focus Not Obscured names cookie banners as a failure cause.

  • Keep a visible, high-contrast focus ring on every control

    Never outline:none without a stronger replacement; 3:1 minimum.

Where CookieBeam Fits

CookieBeam banners are operable by keyboard with real semantics, and dismissing the banner is never recorded as acceptance, non-essential scripts wait for an explicit signal. Because layout, colours, and sizes are configurable, you can set a focus indicator that clears the 3:1 bar rather than inherit a template's invisible one.

Keyboard Focus Management in Cookie Banners | CookieBeam | CookieBeam